blob: 904c0e924ed951a4adfbaca2d83a34bdcb155669 [file] [log] [blame]
Colin Crossf45fa6b2012-03-26 12:38:26 -07001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Felipe Lemef0292972016-11-22 13:57:05 -080016
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070017#define LOG_TAG "dumpstate"
Colin Crossf45fa6b2012-03-26 12:38:26 -070018
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -070019#include <dirent.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070020#include <errno.h>
21#include <fcntl.h>
Felipe Lemead5f6c42015-11-30 14:26:46 -080022#include <libgen.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070023#include <limits.h>
Mark Salyzyn8f37aa52015-06-12 12:28:24 -070024#include <stdbool.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070025#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080028#include <sys/poll.h>
Christopher Ferris7dc7f322014-07-22 16:08:19 -070029#include <sys/prctl.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070030#include <sys/resource.h>
31#include <sys/stat.h>
32#include <sys/time.h>
33#include <sys/wait.h>
34#include <unistd.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070035
36#include <chrono>
37#include <functional>
38#include <future>
Narayan Kamath8f788292017-05-25 13:20:39 +010039#include <memory>
40#include <regex>
41#include <set>
42#include <string>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070043#include <utility>
Narayan Kamath8f788292017-05-25 13:20:39 +010044#include <vector>
Colin Crossf45fa6b2012-03-26 12:38:26 -070045
Felipe Leme96c2bbb2016-09-26 09:21:21 -070046#include <android-base/file.h>
47#include <android-base/properties.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070048#include <android-base/scopeguard.h>
Elliott Hughes9dc117c2015-12-07 14:21:50 -080049#include <android-base/stringprintf.h>
Naveen Kalla058e1e82016-10-19 21:38:44 -070050#include <android-base/strings.h>
Andreas Gampeaff68432016-07-18 18:01:27 -070051#include <android-base/unique_fd.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080052#include <android/hardware/dumpstate/1.0/IDumpstateDevice.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080053#include <android/hidl/manager/1.0/IServiceManager.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080054#include <cutils/native_handle.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070055#include <cutils/properties.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080056#include <dumpsys.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080057#include <hidl/ServiceManagement.h>
Felipe Leme75876a22016-10-27 16:31:27 -070058#include <openssl/sha.h>
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070059#include <private/android_filesystem_config.h>
60#include <private/android_logger.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080061#include <serviceutils/PriorityDumper.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070062#include <utils/StrongPointer.h>
Felipe Lemef0292972016-11-22 13:57:05 -080063#include "DumpstateInternal.h"
Vishnu Naire97d6122018-01-18 13:58:56 -080064#include "DumpstateSectionReporter.h"
Felipe Leme75876a22016-10-27 16:31:27 -070065#include "DumpstateService.h"
Colin Crossf45fa6b2012-03-26 12:38:26 -070066#include "dumpstate.h"
Felipe Leme6e01fa62015-11-11 19:35:14 -080067
Steven Morelandcb7ef822016-11-29 13:20:37 -080068using ::android::hardware::dumpstate::V1_0::IDumpstateDevice;
Vishnu Naire97d6122018-01-18 13:58:56 -080069using ::std::literals::chrono_literals::operator""ms;
70using ::std::literals::chrono_literals::operator""s;
Steven Morelandcb7ef822016-11-29 13:20:37 -080071
Felipe Leme47e9be22016-12-21 15:37:07 -080072// TODO: remove once moved to namespace
Vishnu Naire97d6122018-01-18 13:58:56 -080073using android::defaultServiceManager;
74using android::Dumpsys;
75using android::INVALID_OPERATION;
76using android::IServiceManager;
77using android::OK;
78using android::sp;
79using android::status_t;
80using android::String16;
81using android::String8;
82using android::TIMED_OUT;
83using android::UNKNOWN_ERROR;
84using android::Vector;
Felipe Leme47e9be22016-12-21 15:37:07 -080085using android::os::dumpstate::CommandOptions;
86using android::os::dumpstate::DumpFileToFd;
Vishnu Naire97d6122018-01-18 13:58:56 -080087using android::os::dumpstate::DumpstateSectionReporter;
Felipe Leme47e9be22016-12-21 15:37:07 -080088using android::os::dumpstate::GetPidByName;
Vishnu Naire97d6122018-01-18 13:58:56 -080089using android::os::dumpstate::PropertiesHelper;
Felipe Leme47e9be22016-12-21 15:37:07 -080090
Colin Crossf45fa6b2012-03-26 12:38:26 -070091/* read before root is shed */
92static char cmdline_buf[16384] = "(unknown)";
Yi Kong19d5c002018-07-20 13:39:55 -070093static const char *dump_traces_path = nullptr;
Colin Crossf45fa6b2012-03-26 12:38:26 -070094
Felipe Leme1d486fe2016-10-14 18:06:47 -070095// TODO: variables and functions below should be part of dumpstate object
96
Felipe Leme635ca312016-01-05 14:23:02 -080097static std::set<std::string> mount_points;
98void add_mountinfo();
Felipe Leme78f2c862015-12-21 09:55:22 -080099
Todd Poynor2a83daa2013-11-22 15:44:22 -0800100#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
Mark Salyzyn7d0a7622016-06-24 14:06:15 -0700101#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
Wei Wang509bb5d2017-06-09 14:42:12 -0700102#define BLK_DEV_SYS_DIR "/sys/block"
Todd Poynor2a83daa2013-11-22 15:44:22 -0800103
Felipe Lemee82a27d2016-01-05 13:35:44 -0800104#define RECOVERY_DIR "/cache/recovery"
Mark Salyzynd6ab0112016-03-25 12:56:39 -0700105#define RECOVERY_DATA_DIR "/data/misc/recovery"
Tianjie Xu75d53362018-04-11 16:42:28 -0700106#define UPDATE_ENGINE_LOG_DIR "/data/misc/update_engine_log"
Mark Salyzyn4d42dea2016-04-01 10:03:14 -0700107#define LOGPERSIST_DATA_DIR "/data/misc/logd"
David Brazdild2991962016-06-03 14:40:44 +0100108#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
109#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
Erik Kline08165202016-05-30 11:55:44 +0900110#define WLUTIL "/vendor/xbin/wlutil"
Vishnu Nair36b4cdb2017-11-17 10:27:05 -0800111#define WMTRACE_DATA_DIR "/data/misc/wmtrace"
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700112
Narayan Kamath8f788292017-05-25 13:20:39 +0100113// TODO(narayan): Since this information has to be kept in sync
114// with tombstoned, we should just put it in a common header.
115//
116// File: system/core/debuggerd/tombstoned/tombstoned.cpp
Narayan Kamathbd863722017-06-01 18:50:12 +0100117static const std::string TOMBSTONE_DIR = "/data/tombstones/";
118static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
119static const std::string ANR_DIR = "/data/anr/";
120static const std::string ANR_FILE_PREFIX = "anr_";
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700121
Felipe Lemee844a9d2016-09-21 15:01:39 -0700122// TODO: temporary variables and functions used during C++ refactoring
123static Dumpstate& ds = Dumpstate::GetInstance();
Felipe Leme678727a2016-09-21 17:22:11 -0700124static int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand,
125 const CommandOptions& options = CommandOptions::DEFAULT) {
126 return ds.RunCommand(title, fullCommand, options);
127}
128static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
Felipe Lemebda15a02016-11-16 17:48:25 -0800129 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
Vishnu Nair6921f802017-11-22 09:17:23 -0800130 long dumpsysTimeoutMs = 0) {
131 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs);
Felipe Leme678727a2016-09-21 17:22:11 -0700132}
133static int DumpFile(const std::string& title, const std::string& path) {
134 return ds.DumpFile(title, path);
135}
Felipe Lemee82a27d2016-01-05 13:35:44 -0800136
Felipe Lemee844a9d2016-09-21 15:01:39 -0700137// Relative directory (inside the zip) for all files copied as-is into the bugreport.
138static const std::string ZIP_ROOT_DIR = "FS";
139
Steven Moreland7440ddb2016-12-15 16:13:39 -0800140// Must be hardcoded because dumpstate HAL implementation need SELinux access to it
Jie Song9fbfad02017-06-20 16:29:42 -0700141static const std::string kDumpstateBoardPath = "/bugreports/";
Vishnu Naire97d6122018-01-18 13:58:56 -0800142static const std::string kProtoPath = "proto/";
143static const std::string kProtoExt = ".proto";
Jie Song9fbfad02017-06-20 16:29:42 -0700144static const std::string kDumpstateBoardFiles[] = {
145 "dumpstate_board.txt",
Felipe Leme95d6ca52017-08-01 16:35:56 -0700146 "dumpstate_board.bin"
Jie Song9fbfad02017-06-20 16:29:42 -0700147};
148static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
149
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700150static constexpr char PROPERTY_EXTRA_OPTIONS[] = "dumpstate.options";
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700151static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Lemed071c682016-10-20 16:48:00 -0700152static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
Naveen Kallab53a1c92017-03-16 18:17:25 -0700153static constexpr char PROPERTY_EXTRA_TITLE[] = "dumpstate.options.title";
154static constexpr char PROPERTY_EXTRA_DESCRIPTION[] = "dumpstate.options.description";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700155
Felipe Lemef0292972016-11-22 13:57:05 -0800156static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
157
Narayan Kamath8f788292017-05-25 13:20:39 +0100158/*
Narayan Kamathbd863722017-06-01 18:50:12 +0100159 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
160 * The returned vector is sorted by the mtimes of the dumps. If |limit_by_mtime|
161 * is set, the vector only contains files that were written in the last 30 minutes.
Andreas Gamped0d76952017-08-22 13:08:37 -0700162 * If |limit_by_count| is set, the vector only contains the ten latest files.
Narayan Kamath8f788292017-05-25 13:20:39 +0100163 */
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700164static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
165 const std::string& file_prefix,
166 bool limit_by_mtime,
167 bool limit_by_count = true) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100168 const time_t thirty_minutes_ago = ds.now_ - 60 * 30;
169
Narayan Kamathbd863722017-06-01 18:50:12 +0100170 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100171
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700172 if (dump_dir == nullptr) {
173 MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno));
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700174 return std::vector<DumpData>();
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700175 }
176
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700177 std::vector<DumpData> dump_data;
Narayan Kamathbd863722017-06-01 18:50:12 +0100178 struct dirent* entry = nullptr;
179 while ((entry = readdir(dump_dir.get()))) {
180 if (entry->d_type != DT_REG) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100181 continue;
182 }
183
Narayan Kamathbd863722017-06-01 18:50:12 +0100184 const std::string base_name(entry->d_name);
185 if (base_name.find(file_prefix) != 0) {
186 continue;
187 }
188
189 const std::string abs_path = dir_path + base_name;
190 android::base::unique_fd fd(
191 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
192 if (fd == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700193 MYLOGW("Unable to open dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamathbd863722017-06-01 18:50:12 +0100194 break;
195 }
196
197 struct stat st = {};
198 if (fstat(fd, &st) == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700199 MYLOGW("Unable to stat dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamath8f788292017-05-25 13:20:39 +0100200 continue;
201 }
202
Narayan Kamath3f31b632018-02-22 19:42:36 +0000203 if (limit_by_mtime && st.st_mtime < thirty_minutes_ago) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100204 MYLOGI("Excluding stale dump file: %s\n", abs_path.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100205 continue;
206 }
207
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700208 dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700209 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100210
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700211 // Sort in descending modification time so that we only keep the newest
212 // reports if |limit_by_count| is true.
213 std::sort(dump_data.begin(), dump_data.end(),
214 [](const DumpData& d1, const DumpData& d2) { return d1.mtime > d2.mtime; });
Narayan Kamath8f788292017-05-25 13:20:39 +0100215
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700216 if (limit_by_count && dump_data.size() > 10) {
217 dump_data.erase(dump_data.begin() + 10, dump_data.end());
Andreas Gamped0d76952017-08-22 13:08:37 -0700218 }
219
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700220 return dump_data;
Narayan Kamath8f788292017-05-25 13:20:39 +0100221}
222
Narayan Kamathbd863722017-06-01 18:50:12 +0100223static bool AddDumps(const std::vector<DumpData>::const_iterator start,
224 const std::vector<DumpData>::const_iterator end,
225 const char* type_name, const bool add_to_zip) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100226 bool dumped = false;
Narayan Kamathbd863722017-06-01 18:50:12 +0100227 for (auto it = start; it != end; ++it) {
228 const std::string& name = it->name;
229 const int fd = it->fd;
Narayan Kamath8f788292017-05-25 13:20:39 +0100230 dumped = true;
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100231
232 // Seek to the beginning of the file before dumping any data. A given
233 // DumpData entry might be dumped multiple times in the report.
234 //
235 // For example, the most recent ANR entry is dumped to the body of the
236 // main entry and it also shows up as a separate entry in the bugreport
237 // ZIP file.
238 if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) {
239 MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(),
240 strerror(errno));
241 }
242
Narayan Kamath8f788292017-05-25 13:20:39 +0100243 if (ds.IsZipping() && add_to_zip) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800244 if (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd, /* timeout = */ 0ms) != OK) {
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100245 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100246 }
247 } else {
248 dump_file_from_fd(type_name, name.c_str(), fd);
249 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100250 }
251
252 return dumped;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700253}
254
Felipe Leme635ca312016-01-05 14:23:02 -0800255// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700256void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800257 char path[PATH_MAX];
258
259 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
260 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700261 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800262 char linkname[PATH_MAX];
263 ssize_t r = readlink(path, linkname, PATH_MAX);
264 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800265 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800266 return;
267 }
268 linkname[r] = '\0';
269
270 if (mount_points.find(linkname) == mount_points.end()) {
271 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700272 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700273 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
Felipe Leme635ca312016-01-05 14:23:02 -0800274 mount_points.insert(linkname);
275 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800276 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800277 }
278 }
279}
280
281void add_mountinfo() {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700282 if (!ds.IsZipping()) return;
Felipe Leme678727a2016-09-21 17:22:11 -0700283 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800284 mount_points.clear();
Felipe Leme46b85da2016-11-21 17:40:45 -0800285 DurationReporter duration_reporter(title, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700286 for_each_pid(do_mountinfo, nullptr);
287 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800288}
289
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700290static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
291{
292 DIR *d;
293 struct dirent *de;
294 char path[PATH_MAX];
295
296 d = opendir(driverpath);
Yi Kong19d5c002018-07-20 13:39:55 -0700297 if (d == nullptr) {
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700298 return;
299 }
300
301 while ((de = readdir(d))) {
302 if (de->d_type != DT_LNK) {
303 continue;
304 }
305 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700306 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700307 }
308
309 closedir(d);
310}
311
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700312
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700313
314// dump anrd's trace and add to the zip file.
315// 1. check if anrd is running on this device.
316// 2. send a SIGUSR1 to its pid which will dump anrd's trace.
317// 3. wait until the trace generation completes and add to the zip file.
318static bool dump_anrd_trace() {
319 unsigned int pid;
320 char buf[50], path[PATH_MAX];
321 struct dirent *trace;
322 struct stat st;
323 DIR *trace_dir;
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700324 int retry = 5;
325 long max_ctime = 0, old_mtime;
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700326 long long cur_size = 0;
327 const char *trace_path = "/data/misc/anrd/";
328
Felipe Leme1d486fe2016-10-14 18:06:47 -0700329 if (!ds.IsZipping()) {
330 MYLOGE("Not dumping anrd trace because it's not a zipped bugreport\n");
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700331 return false;
332 }
333
334 // find anrd's pid if it is running.
Dan Willemsen4a0a8342018-05-04 13:05:01 -0700335 pid = GetPidByName("/system/bin/anrd");
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700336
337 if (pid > 0) {
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700338 if (stat(trace_path, &st) == 0) {
339 old_mtime = st.st_mtime;
340 } else {
341 MYLOGE("Failed to find: %s\n", trace_path);
342 return false;
343 }
344
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700345 // send SIGUSR1 to the anrd to generate a trace.
346 sprintf(buf, "%u", pid);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700347 if (RunCommand("ANRD_DUMP", {"kill", "-SIGUSR1", buf},
Felipe Leme30dbfa12016-09-02 12:43:26 -0700348 CommandOptions::WithTimeout(1).Build())) {
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700349 MYLOGE("anrd signal timed out. Please manually collect trace\n");
350 return false;
351 }
352
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700353 while (retry-- > 0 && old_mtime == st.st_mtime) {
354 sleep(1);
355 stat(trace_path, &st);
356 }
357
358 if (retry < 0 && old_mtime == st.st_mtime) {
359 MYLOGE("Failed to stat %s or trace creation timeout\n", trace_path);
360 return false;
361 }
362
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700363 // identify the trace file by its creation time.
364 if (!(trace_dir = opendir(trace_path))) {
365 MYLOGE("Can't open trace file under %s\n", trace_path);
366 }
367 while ((trace = readdir(trace_dir))) {
368 if (strcmp(trace->d_name, ".") == 0
369 || strcmp(trace->d_name, "..") == 0) {
370 continue;
371 }
372 sprintf(path, "%s%s", trace_path, trace->d_name);
373 if (stat(path, &st) == 0) {
374 if (st.st_ctime > max_ctime) {
375 max_ctime = st.st_ctime;
376 sprintf(buf, "%s", trace->d_name);
377 }
378 }
379 }
380 closedir(trace_dir);
381
382 // Wait until the dump completes by checking the size of the trace.
383 if (max_ctime > 0) {
384 sprintf(path, "%s%s", trace_path, buf);
385 while(true) {
386 sleep(1);
387 if (stat(path, &st) == 0) {
388 if (st.st_size == cur_size) {
389 break;
390 } else if (st.st_size > cur_size) {
391 cur_size = st.st_size;
392 } else {
393 return false;
394 }
395 } else {
396 MYLOGE("Cant stat() %s anymore\n", path);
397 return false;
398 }
399 }
400 // Add to the zip file.
Felipe Leme1d486fe2016-10-14 18:06:47 -0700401 if (!ds.AddZipEntry("anrd_trace.txt", path)) {
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700402 MYLOGE("Unable to add anrd_trace file %s to zip file\n", path);
403 } else {
404 if (remove(path)) {
405 MYLOGE("Error removing anrd_trace file %s: %s", path, strerror(errno));
406 }
407 return true;
408 }
409 } else {
410 MYLOGE("Can't stats any trace file under %s\n", trace_path);
411 }
412 }
413 return false;
414}
415
Felipe Lemeefd7e272016-05-18 09:27:16 -0700416static void dump_systrace() {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700417 if (!ds.IsZipping()) {
418 MYLOGD("Not dumping systrace because it's not a zipped bugreport\n");
Felipe Leme71a74ac2016-03-17 15:43:25 -0700419 return;
420 }
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700421 std::string systrace_path = ds.GetPath("-systrace.txt");
Felipe Leme14e034a2016-03-30 18:51:03 -0700422 if (systrace_path.empty()) {
423 MYLOGE("Not dumping systrace because path is empty\n");
424 return;
425 }
Felipe Leme71a74ac2016-03-17 15:43:25 -0700426 const char* path = "/sys/kernel/debug/tracing/tracing_on";
427 long int is_tracing;
428 if (read_file_as_long(path, &is_tracing)) {
429 return; // error already logged
430 }
431 if (is_tracing <= 0) {
432 MYLOGD("Skipping systrace because '%s' content is '%ld'\n", path, is_tracing);
433 return;
434 }
435
Felipe Leme14e034a2016-03-30 18:51:03 -0700436 MYLOGD("Running '/system/bin/atrace --async_dump -o %s', which can take several minutes",
437 systrace_path.c_str());
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700438 if (RunCommand("SYSTRACE", {"/system/bin/atrace", "--async_dump", "-o", systrace_path},
Felipe Leme30dbfa12016-09-02 12:43:26 -0700439 CommandOptions::WithTimeout(120).Build())) {
Felipe Leme14e034a2016-03-30 18:51:03 -0700440 MYLOGE("systrace timed out, its zip entry will be incomplete\n");
Felipe Lemec7fe8fe2016-09-21 18:13:20 -0700441 // TODO: RunCommand tries to kill the process, but atrace doesn't die
Felipe Leme30dbfa12016-09-02 12:43:26 -0700442 // peacefully; ideally, we should call strace to stop itself, but there is no such option
443 // yet (just a --async_stop, which stops and dump
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700444 // if (RunCommand("SYSTRACE", {"/system/bin/atrace", "--kill"})) {
Felipe Leme30dbfa12016-09-02 12:43:26 -0700445 // MYLOGE("could not stop systrace ");
446 // }
Felipe Leme14e034a2016-03-30 18:51:03 -0700447 }
Felipe Leme1d486fe2016-10-14 18:06:47 -0700448 if (!ds.AddZipEntry("systrace.txt", systrace_path)) {
Felipe Leme14e034a2016-03-30 18:51:03 -0700449 MYLOGE("Unable to add systrace file %s to zip file\n", systrace_path.c_str());
Felipe Leme71a74ac2016-03-17 15:43:25 -0700450 } else {
Felipe Leme14e034a2016-03-30 18:51:03 -0700451 if (remove(systrace_path.c_str())) {
452 MYLOGE("Error removing systrace file %s: %s", systrace_path.c_str(), strerror(errno));
453 }
Felipe Leme71a74ac2016-03-17 15:43:25 -0700454 }
455}
456
Mark Salyzyn326842f2015-04-30 09:49:41 -0700457static bool skip_not_stat(const char *path) {
458 static const char stat[] = "/stat";
459 size_t len = strlen(path);
460 if (path[len - 1] == '/') { /* Directory? */
461 return false;
462 }
463 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
464}
465
Felipe Leme4c2d6632016-09-28 14:32:00 -0700466static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800467 return false;
468}
469
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700470unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700471
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800472//
473// stat offsets
474// Name units description
475// ---- ----- -----------
476// read I/Os requests number of read I/Os processed
477#define __STAT_READ_IOS 0
478// read merges requests number of read I/Os merged with in-queue I/O
479#define __STAT_READ_MERGES 1
480// read sectors sectors number of sectors read
481#define __STAT_READ_SECTORS 2
482// read ticks milliseconds total wait time for read requests
483#define __STAT_READ_TICKS 3
484// write I/Os requests number of write I/Os processed
485#define __STAT_WRITE_IOS 4
486// write merges requests number of write I/Os merged with in-queue I/O
487#define __STAT_WRITE_MERGES 5
488// write sectors sectors number of sectors written
489#define __STAT_WRITE_SECTORS 6
490// write ticks milliseconds total wait time for write requests
491#define __STAT_WRITE_TICKS 7
492// in_flight requests number of I/Os currently in flight
493#define __STAT_IN_FLIGHT 8
494// io_ticks milliseconds total time this block device has been active
495#define __STAT_IO_TICKS 9
496// time_in_queue milliseconds total wait time for all requests
497#define __STAT_IN_QUEUE 10
498#define __STAT_NUMBER_FIELD 11
499//
500// read I/Os, write I/Os
501// =====================
502//
503// These values increment when an I/O request completes.
504//
505// read merges, write merges
506// =========================
507//
508// These values increment when an I/O request is merged with an
509// already-queued I/O request.
510//
511// read sectors, write sectors
512// ===========================
513//
514// These values count the number of sectors read from or written to this
515// block device. The "sectors" in question are the standard UNIX 512-byte
516// sectors, not any device- or filesystem-specific block size. The
517// counters are incremented when the I/O completes.
518#define SECTOR_SIZE 512
519//
520// read ticks, write ticks
521// =======================
522//
523// These values count the number of milliseconds that I/O requests have
524// waited on this block device. If there are multiple I/O requests waiting,
525// these values will increase at a rate greater than 1000/second; for
526// example, if 60 read requests wait for an average of 30 ms, the read_ticks
527// field will increase by 60*30 = 1800.
528//
529// in_flight
530// =========
531//
532// This value counts the number of I/O requests that have been issued to
533// the device driver but have not yet completed. It does not include I/O
534// requests that are in the queue but not yet issued to the device driver.
535//
536// io_ticks
537// ========
538//
539// This value counts the number of milliseconds during which the device has
540// had I/O requests queued.
541//
542// time_in_queue
543// =============
544//
545// This value counts the number of milliseconds that I/O requests have waited
546// on this block device. If there are multiple I/O requests waiting, this
547// value will increase as the product of the number of milliseconds times the
548// number of requests waiting (see "read ticks" above for an example).
549#define S_TO_MS 1000
550//
551
Mark Salyzyn326842f2015-04-30 09:49:41 -0700552static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800553 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700554 bool z;
Yi Kong19d5c002018-07-20 13:39:55 -0700555 char *cp, *buffer = nullptr;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700556 size_t i = 0;
Josh Gao7c4258c2018-06-25 13:40:08 -0700557 FILE *fp = fdopen(dup(fd), "rb");
Mark Salyzyn326842f2015-04-30 09:49:41 -0700558 getline(&buffer, &i, fp);
559 fclose(fp);
560 if (!buffer) {
561 return -errno;
562 }
563 i = strlen(buffer);
564 while ((i > 0) && (buffer[i - 1] == '\n')) {
565 buffer[--i] = '\0';
566 }
567 if (!*buffer) {
568 free(buffer);
569 return 0;
570 }
571 z = true;
572 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800573 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700574 if (fields[i] != 0) {
575 z = false;
576 }
577 }
578 if (z) { /* never accessed */
579 free(buffer);
580 return 0;
581 }
582
Wei Wang509bb5d2017-06-09 14:42:12 -0700583 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
584 path += sizeof(BLK_DEV_SYS_DIR) - 1;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700585 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700586
587 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
588 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
589 "W-wait", "in-fli", "activ", "T-wait", path, buffer);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700590 free(buffer);
591
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800592 if (fields[__STAT_IO_TICKS]) {
593 unsigned long read_perf = 0;
594 unsigned long read_ios = 0;
595 if (fields[__STAT_READ_TICKS]) {
596 unsigned long long divisor = fields[__STAT_READ_TICKS]
597 * fields[__STAT_IO_TICKS];
598 read_perf = ((unsigned long long)SECTOR_SIZE
599 * fields[__STAT_READ_SECTORS]
600 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
601 / divisor;
602 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
603 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
604 / divisor;
605 }
606
607 unsigned long write_perf = 0;
608 unsigned long write_ios = 0;
609 if (fields[__STAT_WRITE_TICKS]) {
610 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
611 * fields[__STAT_IO_TICKS];
612 write_perf = ((unsigned long long)SECTOR_SIZE
613 * fields[__STAT_WRITE_SECTORS]
614 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
615 / divisor;
616 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
617 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
618 / divisor;
619 }
620
621 unsigned queue = (fields[__STAT_IN_QUEUE]
622 + (fields[__STAT_IO_TICKS] >> 1))
623 / fields[__STAT_IO_TICKS];
624
625 if (!write_perf && !write_ios) {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700626 printf("%-30s: perf(ios) rd: %luKB/s(%lu/s) q: %u\n", path, read_perf, read_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800627 } else {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700628 printf("%-30s: perf(ios) rd: %luKB/s(%lu/s) wr: %luKB/s(%lu/s) q: %u\n", path, read_perf,
Felipe Lemed8b94e52016-12-08 10:21:44 -0800629 read_ios, write_perf, write_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800630 }
631
632 /* bugreport timeout factor adjustment */
633 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
634 worst_write_perf = write_perf;
635 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700636 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700637 return 0;
638}
639
Yao Chenbe3bbc12018-01-17 16:31:10 -0800640static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
641
642/* timeout in ms to read a list of buffers */
643static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
644 unsigned long timeout_ms = 0;
645 for (const auto& buffer : buffers) {
646 log_id_t id = android_name_to_log_id(buffer.c_str());
647 unsigned long property_size = __android_logger_get_buffer_size(id);
648 /* Engineering margin is ten-fold our guess */
649 timeout_ms += 10 * (property_size + worst_write_perf) / worst_write_perf;
650 }
651 return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700652}
653
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700654void Dumpstate::PrintHeader() const {
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700655 std::string build, fingerprint, radio, bootloader, network;
656 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700657
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700658 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
659 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700660 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
661 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
662 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700663 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
Colin Crossf45fa6b2012-03-26 12:38:26 -0700664
Felipe Lemed8b94e52016-12-08 10:21:44 -0800665 printf("========================================================\n");
666 printf("== dumpstate: %s\n", date);
667 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700668
Felipe Lemed8b94e52016-12-08 10:21:44 -0800669 printf("\n");
670 printf("Build: %s\n", build.c_str());
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700671 // NOTE: fingerprint entry format is important for other tools.
Felipe Lemed8b94e52016-12-08 10:21:44 -0800672 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
673 printf("Bootloader: %s\n", bootloader.c_str());
674 printf("Radio: %s\n", radio.c_str());
675 printf("Network: %s\n", network.c_str());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700676
Felipe Lemed8b94e52016-12-08 10:21:44 -0800677 printf("Kernel: ");
Felipe Lemef0292972016-11-22 13:57:05 -0800678 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
Felipe Lemed8b94e52016-12-08 10:21:44 -0800679 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
Felipe Leme7709f8a2017-12-05 09:30:09 -0800680 printf("Uptime: ");
681 RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"},
682 CommandOptions::WithTimeout(1).Always().Build());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800683 printf("Bugreport format version: %s\n", version_.c_str());
684 printf("Dumpstate info: id=%d pid=%d dry_run=%d args=%s extra_options=%s\n", id_, pid_,
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100685 PropertiesHelper::IsDryRun(), options_->args.c_str(), options_->extra_options.c_str());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800686 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800687}
688
Felipe Leme24b66ee2016-06-16 10:55:26 -0700689// List of file extensions that can cause a zip file attachment to be rejected by some email
690// service providers.
691static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
692 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
693 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
694 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
695};
696
Vishnu Naire97d6122018-01-18 13:58:56 -0800697status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd,
698 std::chrono::milliseconds timeout = 0ms) {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700699 if (!IsZipping()) {
700 MYLOGD("Not adding zip entry %s from fd because it's not a zipped bugreport\n",
701 entry_name.c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -0800702 return INVALID_OPERATION;
Felipe Leme111b9d02016-02-03 09:28:24 -0800703 }
Felipe Leme24b66ee2016-06-16 10:55:26 -0700704 std::string valid_name = entry_name;
705
706 // Rename extension if necessary.
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -0700707 size_t idx = entry_name.rfind('.');
Felipe Leme24b66ee2016-06-16 10:55:26 -0700708 if (idx != std::string::npos) {
709 std::string extension = entry_name.substr(idx);
710 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
711 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
712 valid_name = entry_name + ".renamed";
713 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
714 }
715 }
716
Felipe Leme6fe9db62016-02-12 09:04:16 -0800717 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
718 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700719 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), ZipWriter::kCompress,
720 get_mtime(fd, ds.now_));
Felipe Leme1d486fe2016-10-14 18:06:47 -0700721 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700722 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700723 ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800724 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800725 }
Vishnu Naire97d6122018-01-18 13:58:56 -0800726 auto start = std::chrono::steady_clock::now();
727 auto end = start + timeout;
728 struct pollfd pfd = {fd, POLLIN};
Felipe Lemee82a27d2016-01-05 13:35:44 -0800729
Felipe Leme770410d2016-01-26 17:07:14 -0800730 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800731 while (1) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800732 if (timeout.count() > 0) {
733 // lambda to recalculate the timeout.
734 auto time_left_ms = [end]() {
735 auto now = std::chrono::steady_clock::now();
736 auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
737 return std::max(diff.count(), 0LL);
738 };
739
740 int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
741 if (rc < 0) {
742 MYLOGE("Error in poll while adding from fd to zip entry %s:%s", entry_name.c_str(),
743 strerror(errno));
744 return -errno;
745 } else if (rc == 0) {
746 MYLOGE("Timed out adding from fd to zip entry %s:%s Timeout:%lldms",
747 entry_name.c_str(), strerror(errno), timeout.count());
748 return TIMED_OUT;
749 }
750 }
751
Zach Riggle22200402016-08-18 01:01:24 -0400752 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800753 if (bytes_read == 0) {
754 break;
755 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800756 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800757 return -errno;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800758 }
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700759 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800760 if (err) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700761 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800762 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800763 }
764 }
765
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700766 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700767 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700768 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800769 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800770 }
771
Vishnu Naire97d6122018-01-18 13:58:56 -0800772 return OK;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800773}
774
Felipe Leme1d486fe2016-10-14 18:06:47 -0700775bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
776 android::base::unique_fd fd(
777 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700778 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800779 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800780 return false;
781 }
782
Vishnu Naire97d6122018-01-18 13:58:56 -0800783 return (AddZipEntryFromFd(entry_name, fd.get()) == OK);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800784}
785
786/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700787static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800788 return (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) == OK) ? 0 : 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800789}
790
Felipe Leme1d486fe2016-10-14 18:06:47 -0700791void Dumpstate::AddDir(const std::string& dir, bool recursive) {
792 if (!IsZipping()) {
793 MYLOGD("Not adding dir %s because it's not a zipped bugreport\n", dir.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800794 return;
795 }
Felipe Leme678727a2016-09-21 17:22:11 -0700796 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
Felipe Leme46b85da2016-11-21 17:40:45 -0800797 DurationReporter duration_reporter(dir, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700798 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800799}
800
Felipe Leme1d486fe2016-10-14 18:06:47 -0700801bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
802 if (!IsZipping()) {
803 MYLOGD("Not adding text zip entry %s because it's not a zipped bugreport\n",
804 entry_name.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800805 return false;
806 }
Felipe Lemecbce55d2016-02-08 09:53:18 -0800807 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700808 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, ds.now_);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700809 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700810 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700811 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800812 return false;
813 }
814
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700815 err = zip_writer_->WriteBytes(content.c_str(), content.length());
Felipe Leme1d486fe2016-10-14 18:06:47 -0700816 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700817 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700818 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800819 return false;
820 }
821
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700822 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700823 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700824 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800825 return false;
826 }
827
828 return true;
829}
830
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800831static void DoKmsg() {
832 struct stat st;
833 if (!stat(PSTORE_LAST_KMSG, &st)) {
834 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
835 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
836 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
837 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
838 } else {
839 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
840 DumpFile("LAST KMSG", "/proc/last_kmsg");
841 }
842}
843
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800844static void DoKernelLogcat() {
Yao Chenbe3bbc12018-01-17 16:31:10 -0800845 unsigned long timeout_ms = logcat_timeout({"kernel"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800846 RunCommand(
847 "KERNEL LOG",
848 {"logcat", "-b", "kernel", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
849 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
850}
851
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800852static void DoLogcat() {
Vishnu Nair6921f802017-11-22 09:17:23 -0800853 unsigned long timeout_ms;
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800854 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
855 // calculate timeout
Yao Chenbe3bbc12018-01-17 16:31:10 -0800856 timeout_ms = logcat_timeout({"main", "system", "crash"});
Tony Makae737652017-03-30 17:47:09 +0100857 RunCommand("SYSTEM LOG",
Vishnu Nair6921f802017-11-22 09:17:23 -0800858 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
859 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -0800860 timeout_ms = logcat_timeout({"events"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800861 RunCommand(
862 "EVENT LOG",
863 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
864 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -0800865 timeout_ms = logcat_timeout({"stats"});
866 RunCommand(
867 "STATS LOG",
868 {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
869 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
870 timeout_ms = logcat_timeout({"radio"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800871 RunCommand(
872 "RADIO LOG",
873 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
874 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800875
876 RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
877
878 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800879 RunCommand("LAST LOGCAT", {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable",
880 "-v", "uid", "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800881}
882
Jayachandran Ca94c7172017-06-10 15:08:12 -0700883static void DumpIpTablesAsRoot() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700884 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
885 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +0900886 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -0700887 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +0900888 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
889 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
890 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
891 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -0700892}
893
Narayan Kamath8f788292017-05-25 13:20:39 +0100894static void AddAnrTraceDir(const bool add_to_zip, const std::string& anr_traces_dir) {
895 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
896 anr_traces_dir.c_str());
897
898 // If we're here, dump_traces_path will always be a temporary file
899 // (created with mkostemp or similar) that contains dumps taken earlier
900 // on in the process.
901 if (dump_traces_path != nullptr) {
902 if (add_to_zip) {
903 ds.AddZipEntry(ZIP_ROOT_DIR + anr_traces_dir + "/traces-just-now.txt", dump_traces_path);
904 } else {
905 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
906 dump_traces_path);
907 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
908 }
909
910 const int ret = unlink(dump_traces_path);
911 if (ret == -1) {
912 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
913 strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -0700914 }
915 }
916
Narayan Kamathbd863722017-06-01 18:50:12 +0100917 // Add a specific message for the first ANR Dump.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700918 if (ds.anr_data_.size() > 0) {
919 AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1,
Narayan Kamathbd863722017-06-01 18:50:12 +0100920 "VM TRACES AT LAST ANR", add_to_zip);
921
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100922 // The "last" ANR will always be included as separate entry in the zip file. In addition,
923 // it will be present in the body of the main entry if |add_to_zip| == false.
924 //
925 // Historical ANRs are always included as separate entries in the bugreport zip file.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700926 AddDumps(ds.anr_data_.begin() + ((add_to_zip) ? 1 : 0), ds.anr_data_.end(),
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100927 "HISTORICAL ANR", true /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +0100928 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +0100929 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
930 }
931}
932
933static void AddAnrTraceFiles() {
934 const bool add_to_zip = ds.IsZipping() && ds.version_ == VERSION_SPLIT_ANR;
935
Elliott Hughes69fe5ec2018-03-23 11:04:25 -0700936 std::string anr_traces_dir = "/data/anr";
Narayan Kamath8f788292017-05-25 13:20:39 +0100937
Elliott Hughes69fe5ec2018-03-23 11:04:25 -0700938 AddAnrTraceDir(add_to_zip, anr_traces_dir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100939
Elliott Hughes69fe5ec2018-03-23 11:04:25 -0700940 // Slow traces for slow operations.
Felipe Lemee184f662016-10-27 10:04:47 -0700941 struct stat st;
Elliott Hughes69fe5ec2018-03-23 11:04:25 -0700942 int i = 0;
943 while (true) {
944 const std::string slow_trace_path =
945 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
946 if (stat(slow_trace_path.c_str(), &st)) {
947 // No traces file at this index, done with the files.
948 break;
Felipe Lemee184f662016-10-27 10:04:47 -0700949 }
Elliott Hughes69fe5ec2018-03-23 11:04:25 -0700950 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
951 i++;
Felipe Lemee184f662016-10-27 10:04:47 -0700952 }
953}
954
Wei Wang509bb5d2017-06-09 14:42:12 -0700955static void DumpBlockStatFiles() {
956 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -0700957
Wei Wang1dc1ef52017-06-12 11:28:37 -0700958 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
959
960 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -0700961 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
962 return;
963 }
964
965 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -0700966 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -0700967 if ((d->d_name[0] == '.')
968 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
969 || (d->d_name[1] == '\0'))) {
970 continue;
971 }
972 const std::string new_path =
973 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
974 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
975 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
976 printf("\n");
977 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700978 return;
Wei Wang509bb5d2017-06-09 14:42:12 -0700979}
Jayachandran Ca94c7172017-06-10 15:08:12 -0700980
981static void DumpPacketStats() {
982 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
983 DumpFile("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
984 DumpFile("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
985 DumpFile("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
986 DumpFile("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
987}
988
989static void DumpIpAddrAndRules() {
990 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
991 RunCommand("NETWORK INTERFACES", {"ip", "link"});
992 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
993 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
994 RunCommand("IP RULES", {"ip", "rule", "show"});
995 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
996}
997
Vishnu Nair64afc022018-02-01 15:29:34 -0800998static void RunDumpsysTextByPriority(const std::string& title, int priority,
999 std::chrono::milliseconds timeout,
1000 std::chrono::milliseconds service_timeout) {
1001 auto start = std::chrono::steady_clock::now();
Vishnu Naire97d6122018-01-18 13:58:56 -08001002 sp<android::IServiceManager> sm = defaultServiceManager();
1003 Dumpsys dumpsys(sm.get());
Vishnu Naire97d6122018-01-18 13:58:56 -08001004 Vector<String16> args;
1005 Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
Vishnu Naire97d6122018-01-18 13:58:56 -08001006 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1007 for (const String16& service : services) {
1008 std::string path(title);
1009 path.append(" - ").append(String8(service).c_str());
1010 DumpstateSectionReporter section_reporter(path, ds.listener_, ds.report_section_);
1011 size_t bytes_written = 0;
1012 status_t status = dumpsys.startDumpThread(service, args);
1013 if (status == OK) {
1014 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1015 std::chrono::duration<double> elapsed_seconds;
1016 status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
1017 /* as_proto = */ false, elapsed_seconds, bytes_written);
1018 section_reporter.setSize(bytes_written);
1019 dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
1020 bool dump_complete = (status == OK);
1021 dumpsys.stopDumpThread(dump_complete);
1022 }
1023 section_reporter.setStatus(status);
1024
1025 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1026 std::chrono::steady_clock::now() - start);
1027 if (elapsed_duration > timeout) {
1028 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1029 elapsed_duration.count());
1030 break;
1031 }
1032 }
1033}
1034
Vishnu Nair64afc022018-02-01 15:29:34 -08001035static void RunDumpsysText(const std::string& title, int priority,
1036 std::chrono::milliseconds timeout,
1037 std::chrono::milliseconds service_timeout) {
1038 DurationReporter duration_reporter(title);
1039 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1040 fsync(STDOUT_FILENO);
1041 RunDumpsysTextByPriority(title, priority, timeout, service_timeout);
1042}
1043
1044/* Dump all services registered with Normal or Default priority. */
1045static void RunDumpsysTextNormalPriority(const std::string& title,
1046 std::chrono::milliseconds timeout,
1047 std::chrono::milliseconds service_timeout) {
1048 DurationReporter duration_reporter(title);
1049 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1050 fsync(STDOUT_FILENO);
1051 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout,
1052 service_timeout);
1053 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1054 service_timeout);
1055}
1056
1057static void RunDumpsysProto(const std::string& title, int priority,
1058 std::chrono::milliseconds timeout,
1059 std::chrono::milliseconds service_timeout) {
Luis Hector Chavez1e27b082018-03-22 15:36:42 -07001060 if (!ds.IsZipping()) {
1061 MYLOGD("Not dumping %s because it's not a zipped bugreport\n", title.c_str());
1062 return;
1063 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001064 sp<android::IServiceManager> sm = defaultServiceManager();
1065 Dumpsys dumpsys(sm.get());
1066 Vector<String16> args;
1067 Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
1068 DurationReporter duration_reporter(title);
1069
1070 auto start = std::chrono::steady_clock::now();
1071 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
1072 for (const String16& service : services) {
1073 std::string path(kProtoPath);
1074 path.append(String8(service).c_str());
1075 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
1076 path.append("_CRITICAL");
1077 } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
1078 path.append("_HIGH");
1079 }
1080 path.append(kProtoExt);
1081 DumpstateSectionReporter section_reporter(path, ds.listener_, ds.report_section_);
1082 status_t status = dumpsys.startDumpThread(service, args);
1083 if (status == OK) {
1084 status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
1085 bool dumpTerminated = (status == OK);
1086 dumpsys.stopDumpThread(dumpTerminated);
1087 }
1088 ZipWriter::FileEntry file_entry;
1089 ds.zip_writer_->GetLastEntry(&file_entry);
1090 section_reporter.setSize(file_entry.compressed_size);
1091 section_reporter.setStatus(status);
1092
1093 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1094 std::chrono::steady_clock::now() - start);
1095 if (elapsed_duration > timeout) {
1096 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1097 elapsed_duration.count());
1098 break;
1099 }
1100 }
1101}
1102
Vishnu Nair780b1282017-10-10 13:57:24 -07001103// Runs dumpsys on services that must dump first and and will take less than 100ms to dump.
1104static void RunDumpsysCritical() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001105 RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1106 /* timeout= */ 5s, /* service_timeout= */ 500ms);
1107 RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1108 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Vishnu Nair780b1282017-10-10 13:57:24 -07001109}
1110
1111// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
1112static void RunDumpsysHigh() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001113 // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
1114 // high priority. Reduce timeout once they are able to dump in a shorter time or
1115 // moved to a parallel task.
1116 RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1117 /* timeout= */ 90s, /* service_timeout= */ 30s);
1118 RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1119 /* timeout= */ 5s, /* service_timeout= */ 1s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001120}
1121
1122// Runs dumpsys on services that must dump but can take up to 10s to dump.
1123static void RunDumpsysNormal() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001124 RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
1125 RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1126 /* timeout= */ 90s, /* service_timeout= */ 10s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001127}
1128
Steven Moreland44cd9482018-01-04 16:24:13 -08001129static void DumpHals() {
Steven Moreland44cd9482018-01-04 16:24:13 -08001130 using android::hidl::manager::V1_0::IServiceManager;
1131 using android::hardware::defaultServiceManager;
1132
1133 sp<IServiceManager> sm = defaultServiceManager();
1134 if (sm == nullptr) {
1135 MYLOGE("Could not retrieve hwservicemanager to dump hals.\n");
1136 return;
1137 }
1138
1139 auto ret = sm->list([&](const auto& interfaces) {
1140 for (const std::string& interface : interfaces) {
1141 std::string cleanName = interface;
1142 std::replace_if(cleanName.begin(),
1143 cleanName.end(),
1144 [](char c) {
1145 return !isalnum(c) &&
1146 std::string("@-_:.").find(c) == std::string::npos;
1147 }, '_');
1148 const std::string path = kDumpstateBoardPath + "lshal_debug_" + cleanName;
1149
1150 {
1151 auto fd = android::base::unique_fd(
1152 TEMP_FAILURE_RETRY(open(path.c_str(),
1153 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1154 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1155 if (fd < 0) {
1156 MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str());
1157 continue;
1158 }
1159 RunCommandToFd(fd,
1160 "",
Steven Morelandc81cd3c2018-01-18 14:36:26 -08001161 {"lshal", "debug", "-E", interface},
Steven Moreland44cd9482018-01-04 16:24:13 -08001162 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1163
1164 bool empty = 0 == lseek(fd, 0, SEEK_END);
1165 if (!empty) {
1166 ds.AddZipEntry("lshal-debug/" + cleanName + ".txt", path);
1167 }
1168 }
1169
1170 unlink(path.c_str());
1171 }
1172 });
1173
1174 if (!ret.isOk()) {
1175 MYLOGE("Could not list hals from hwservicemanager.\n");
1176 }
1177}
1178
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001179static void dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001180 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001181
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001182 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001183 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001184 DumpBlockStatFiles();
Mark Salyzyn8c8130e2015-12-09 11:21:28 -08001185 dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001186 DumpFile("MEMORY INFO", "/proc/meminfo");
1187 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001188 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Felipe Lemef0292972016-11-22 13:57:05 -08001189 RunCommand("PROCRANK", {"procrank"}, AS_ROOT_20);
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001190 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1191 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1192 DumpFile("SLAB INFO", "/proc/slabinfo");
1193 DumpFile("ZONEINFO", "/proc/zoneinfo");
1194 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1195 DumpFile("BUDDYINFO", "/proc/buddyinfo");
1196 DumpFile("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001197
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001198 DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources");
1199 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
1200 DumpFile("KERNEL SYNC", "/d/sync");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001201
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001202 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001203 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Felipe Lemef0292972016-11-22 13:57:05 -08001204 RunCommand("LIBRANK", {"librank"}, CommandOptions::AS_ROOT);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001205
Andreas Huber69ec3ac2017-03-23 09:47:51 -07001206 if (ds.IsZipping()) {
Yifan Hong90e8d8d2018-06-28 13:14:39 -07001207 RunCommand("HARDWARE HALS", {"lshal", "-lVSietrpc", "--types=b,c,l,z"},
1208 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
Steven Moreland44cd9482018-01-04 16:24:13 -08001209 DumpHals();
Andreas Huber69ec3ac2017-03-23 09:47:51 -07001210 } else {
Yifan Hong90e8d8d2018-06-28 13:14:39 -07001211 RunCommand("HARDWARE HALS", {"lshal", "-lVSietrpc", "--types=b,c,l,z", "--debug"},
1212 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
Andreas Huber69ec3ac2017-03-23 09:47:51 -07001213 }
Steven Moreland81b429e2017-01-31 19:50:46 -08001214
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001215 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001216 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001217 struct stat s;
1218 if (stat("/proc/modules", &s) != 0) {
1219 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1220 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001221 RunCommand("LSMOD", {"lsmod"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001222 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001223
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001224 if (__android_logger_property_get_bool(
1225 "ro.logd.kernel", BOOL_DEFAULT_TRUE | BOOL_DEFAULT_FLAG_ENG | BOOL_DEFAULT_FLAG_SVELTE)) {
1226 DoKernelLogcat();
1227 } else {
1228 do_dmesg();
1229 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001230
Felipe Lemef0292972016-11-22 13:57:05 -08001231 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Jeff Brown1dc94e32014-09-11 14:15:27 -07001232 for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES");
1233 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001234 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001235
Ajay Panicker2ff8e872017-04-27 14:04:32 -07001236 /* Dump Bluetooth HCI logs */
1237 ds.AddDir("/data/misc/bluetooth/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001238
Felipe Leme9a523ae2016-10-20 15:10:33 -07001239 if (!ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001240 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001241 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001242 }
1243
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001244 DoLogcat();
Mark Salyzynecc07632015-07-30 14:57:09 -07001245
Felipe Lemee184f662016-10-27 10:04:47 -07001246 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001247
Narayan Kamath8f788292017-05-25 13:20:39 +01001248 // NOTE: tombstones are always added as separate entries in the zip archive
1249 // and are not interspersed with the main report.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001250 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
Narayan Kamathbd863722017-06-01 18:50:12 +01001251 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001252 if (!tombstones_dumped) {
1253 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001254 }
1255
Jayachandran Ca94c7172017-06-10 15:08:12 -07001256 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001257
Chenbo Feng276a3b62018-08-07 11:44:49 -07001258 RunDumpsys("EBPF MAP STATS", {"netd", "trafficcontroller"});
1259
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001260 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001261
Jayachandran Ca94c7172017-06-10 15:08:12 -07001262 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001263
1264 dump_route_tables();
1265
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001266 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1267 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1268 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001269
Vishnu Nair780b1282017-10-10 13:57:24 -07001270 RunDumpsysHigh();
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001271
Elliott Hughes23ccc622017-02-28 10:14:22 -08001272 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001273
Jin Qianf334d662017-10-10 14:41:37 -07001274 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001275
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001276 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001277
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001278 RunCommand("LAST RADIO LOG", {"parse_radio_log", "/proc/last_radio_log"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001279
Colin Crossf45fa6b2012-03-26 12:38:26 -07001280 /* Binder state is expensive to look at as it uses a lot of memory. */
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001281 DumpFile("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
1282 DumpFile("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
1283 DumpFile("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
1284 DumpFile("BINDER STATS", "/sys/kernel/debug/binder/stats");
1285 DumpFile("BINDER STATE", "/sys/kernel/debug/binder/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001286
Vishnu Nair36b4cdb2017-11-17 10:27:05 -08001287 /* Add window and surface trace files. */
1288 if (!PropertiesHelper::IsUserBuild()) {
1289 ds.AddDir(WMTRACE_DATA_DIR, false);
1290 }
1291
Felipe Leme6f674ae2016-11-18 17:10:33 -08001292 ds.DumpstateBoard();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001293
Steven Moreland7440ddb2016-12-15 16:13:39 -08001294 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001295 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1296 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001297 // su does not exist on user builds, so try running without it.
1298 // This way any implementations of vril-dump that do not require
1299 // root can run on user builds.
1300 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001301 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001302 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001303 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001304 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001305 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001306 }
1307
Felipe Lemed8b94e52016-12-08 10:21:44 -08001308 printf("========================================================\n");
1309 printf("== Android Framework Services\n");
1310 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001311
Vishnu Nair780b1282017-10-10 13:57:24 -07001312 RunDumpsysNormal();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001313
Felipe Lemed8b94e52016-12-08 10:21:44 -08001314 printf("========================================================\n");
1315 printf("== Checkins\n");
1316 printf("========================================================\n");
Dianne Hackborn02bea972013-06-26 18:59:09 -07001317
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001318 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1319 RunDumpsys("CHECKIN MEMINFO", {"meminfo", "--checkin"});
1320 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"});
1321 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"});
1322 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"});
1323 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"});
Dianne Hackborn02bea972013-06-26 18:59:09 -07001324
Felipe Lemed8b94e52016-12-08 10:21:44 -08001325 printf("========================================================\n");
1326 printf("== Running Application Activities\n");
1327 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001328
Makoto Onuki60780982018-04-16 15:34:00 -07001329 // The following dumpsys internally collects output from running apps, so it can take a long
1330 // time. So let's extend the timeout.
1331
1332 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1333
1334 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001335
Felipe Lemed8b94e52016-12-08 10:21:44 -08001336 printf("========================================================\n");
Makoto Onuki60780982018-04-16 15:34:00 -07001337 printf("== Running Application Services (platform)\n");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001338 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001339
Vishnu Nairc6e6ea72018-07-02 14:20:06 -07001340 RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
Makoto Onuki60780982018-04-16 15:34:00 -07001341 DUMPSYS_COMPONENTS_OPTIONS);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001342
Felipe Lemed8b94e52016-12-08 10:21:44 -08001343 printf("========================================================\n");
Makoto Onuki60780982018-04-16 15:34:00 -07001344 printf("== Running Application Services (non-platform)\n");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001345 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001346
Makoto Onuki60780982018-04-16 15:34:00 -07001347 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1348 DUMPSYS_COMPONENTS_OPTIONS);
1349
1350 printf("========================================================\n");
1351 printf("== Running Application Providers (platform)\n");
1352 printf("========================================================\n");
1353
1354 RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
1355 DUMPSYS_COMPONENTS_OPTIONS);
1356
1357 printf("========================================================\n");
1358 printf("== Running Application Providers (non-platform)\n");
1359 printf("========================================================\n");
1360
1361 RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1362 DUMPSYS_COMPONENTS_OPTIONS);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001363
Adrian Roos8b397ab2017-04-04 16:35:44 -07001364 printf("========================================================\n");
1365 printf("== Dropbox crashes\n");
1366 printf("========================================================\n");
1367
1368 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1369 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1370
Felipe Lemed8b94e52016-12-08 10:21:44 -08001371 printf("========================================================\n");
1372 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1373 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1374 printf("========================================================\n");
1375 printf("== dumpstate: done (id %d)\n", ds.id_);
1376 printf("========================================================\n");
Bookatz38472142018-09-28 10:20:24 -07001377
1378 printf("========================================================\n");
1379 printf("== Obtaining statsd metadata\n");
1380 printf("========================================================\n");
1381 // This differs from the usual dumpsys stats, which is the stats report data.
1382 RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001383}
1384
Nandana Dutt4be45d12018-09-26 15:04:23 +01001385/* Dumps state for the default case. Returns true if everything went fine. */
1386static bool DumpstateDefault() {
1387 // Dumps systrace right away, otherwise it will be filled with unnecessary events.
1388 // First try to dump anrd trace if the daemon is running. Otherwise, dump
1389 // the raw trace.
1390 if (!dump_anrd_trace()) {
1391 dump_systrace();
1392 }
1393
1394 // Invoking the following dumpsys calls before dump_traces() to try and
1395 // keep the system stats as close to its initial state as possible.
1396 RunDumpsysCritical();
1397
1398 /* collect stack traces from Dalvik and native processes (needs root) */
1399 dump_traces_path = dump_traces();
1400
1401 /* Run some operations that require root. */
1402 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping());
1403 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping());
1404
1405 ds.AddDir(RECOVERY_DIR, true);
1406 ds.AddDir(RECOVERY_DATA_DIR, true);
1407 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
1408 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1409 if (!PropertiesHelper::IsUserBuild()) {
1410 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1411 ds.AddDir(PROFILE_DATA_DIR_REF, true);
1412 }
1413 add_mountinfo();
1414 DumpIpTablesAsRoot();
1415
1416 // Capture any IPSec policies in play. No keys are exposed here.
1417 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1418
1419 // Run ss as root so we can see socket marks.
1420 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1421
1422 // Run iotop as root to show top 100 IO threads
1423 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1424
1425 if (!DropRootUser()) {
1426 return false;
1427 }
1428
1429 dumpstate();
1430 return true;
1431}
1432
mukesh agrawal253dad42018-01-23 21:59:59 -08001433// This method collects common dumpsys for telephony and wifi
1434static void DumpstateRadioCommon() {
Jayachandran Ca94c7172017-06-10 15:08:12 -07001435 DumpIpTablesAsRoot();
1436
1437 if (!DropRootUser()) {
1438 return;
1439 }
1440
1441 do_dmesg();
1442 DoLogcat();
1443 DumpPacketStats();
1444 DoKmsg();
1445 DumpIpAddrAndRules();
1446 dump_route_tables();
1447
1448 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
1449 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08001450}
1451
1452// This method collects dumpsys for telephony debugging only
1453static void DumpstateTelephonyOnly() {
1454 DurationReporter duration_reporter("DUMPSTATE");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001455 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
mukesh agrawal253dad42018-01-23 21:59:59 -08001456
1457 DumpstateRadioCommon();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001458
1459 RunCommand("SYSTEM PROPERTIES", {"getprop"});
1460
1461 printf("========================================================\n");
1462 printf("== Android Framework Services\n");
1463 printf("========================================================\n");
1464
Vishnu Nair652cc802017-11-30 15:18:30 -08001465 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1466 SEC_TO_MSEC(10));
1467 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
1468 SEC_TO_MSEC(10));
Amruth Ramachandrand25a9142018-04-02 16:16:09 -07001469 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
1470 SEC_TO_MSEC(10));
Sooraj Sasindrane8d98912018-04-20 11:31:55 -07001471 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
1472 SEC_TO_MSEC(10));
Jayachandran Ca94c7172017-06-10 15:08:12 -07001473
1474 printf("========================================================\n");
1475 printf("== Running Application Services\n");
1476 printf("========================================================\n");
1477
1478 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
1479
1480 printf("========================================================\n");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001481 printf("== Running Application Services (non-platform)\n");
1482 printf("========================================================\n");
1483
1484 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1485 DUMPSYS_COMPONENTS_OPTIONS);
1486
1487 printf("========================================================\n");
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07001488 printf("== Checkins\n");
1489 printf("========================================================\n");
1490
1491 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1492
1493 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07001494 printf("== dumpstate: done (id %d)\n", ds.id_);
1495 printf("========================================================\n");
1496}
1497
mukesh agrawal253dad42018-01-23 21:59:59 -08001498// This method collects dumpsys for wifi debugging only
1499static void DumpstateWifiOnly() {
1500 DurationReporter duration_reporter("DUMPSTATE");
1501
1502 DumpstateRadioCommon();
1503
1504 printf("========================================================\n");
1505 printf("== Android Framework Services\n");
1506 printf("========================================================\n");
1507
1508 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1509 SEC_TO_MSEC(10));
1510 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
1511 SEC_TO_MSEC(10));
1512
1513 printf("========================================================\n");
1514 printf("== dumpstate: done (id %d)\n", ds.id_);
1515 printf("========================================================\n");
1516}
1517
Felipe Leme6f674ae2016-11-18 17:10:33 -08001518void Dumpstate::DumpstateBoard() {
1519 DurationReporter duration_reporter("dumpstate_board()");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001520 printf("========================================================\n");
1521 printf("== Board\n");
1522 printf("========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001523
Felipe Leme6f674ae2016-11-18 17:10:33 -08001524 if (!IsZipping()) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08001525 MYLOGD("Not dumping board info because it's not a zipped bugreport\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001526 return;
1527 }
1528
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001529 std::vector<std::string> paths;
1530 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07001531 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001532 paths.emplace_back(kDumpstateBoardPath + kDumpstateBoardFiles[i]);
1533 remover.emplace_back(android::base::make_scope_guard(std::bind(
1534 [](std::string path) {
1535 if (remove(path.c_str()) != 0 && errno != ENOENT) {
1536 MYLOGE("Could not remove(%s): %s\n", path.c_str(), strerror(errno));
1537 }
1538 },
1539 paths[i])));
1540 }
Jie Song9fbfad02017-06-20 16:29:42 -07001541
Wei Wang587eac92018-04-05 12:17:20 -07001542 sp<IDumpstateDevice> dumpstate_device(IDumpstateDevice::getService());
1543 if (dumpstate_device == nullptr) {
1544 MYLOGE("No IDumpstateDevice implementation\n");
1545 return;
1546 }
1547
1548 using ScopedNativeHandle =
1549 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
1550 ScopedNativeHandle handle(native_handle_create(static_cast<int>(paths.size()), 0),
1551 [](native_handle_t* handle) {
1552 native_handle_close(handle);
1553 native_handle_delete(handle);
1554 });
1555 if (handle == nullptr) {
1556 MYLOGE("Could not create native_handle\n");
1557 return;
1558 }
1559
1560 for (size_t i = 0; i < paths.size(); i++) {
1561 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
1562
1563 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
1564 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1565 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1566 if (fd < 0) {
1567 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
1568 return;
1569 }
1570 handle.get()->data[i] = fd.release();
1571 }
1572
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001573 // Given that bugreport is required to diagnose failures, it's better to
Wei Wang587eac92018-04-05 12:17:20 -07001574 // set an arbitrary amount of timeout for IDumpstateDevice than to block the
1575 // rest of bugreport. In the timeout case, we will kill dumpstate board HAL
1576 // and grab whatever dumped
1577 std::packaged_task<bool()>
1578 dumpstate_task([paths, dumpstate_device, &handle]() -> bool {
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001579 android::hardware::Return<void> status = dumpstate_device->dumpstateBoard(handle.get());
1580 if (!status.isOk()) {
1581 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
Wei Wang587eac92018-04-05 12:17:20 -07001582 return false;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001583 }
Wei Wang587eac92018-04-05 12:17:20 -07001584 return true;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001585 });
Wei Wang587eac92018-04-05 12:17:20 -07001586
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001587 auto result = dumpstate_task.get_future();
1588 std::thread(std::move(dumpstate_task)).detach();
Wei Wang587eac92018-04-05 12:17:20 -07001589
1590 constexpr size_t timeout_sec = 30;
1591 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
1592 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate vendor HAL\n", timeout_sec);
1593 if (!android::base::SetProperty("ctl.interface_restart",
1594 android::base::StringPrintf("%s/default",
1595 IDumpstateDevice::descriptor))) {
1596 MYLOGE("Couldn't restart dumpstate HAL\n");
1597 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001598 }
Wei Wang587eac92018-04-05 12:17:20 -07001599 // Wait some time for init to kill dumpstate vendor HAL
1600 constexpr size_t killing_timeout_sec = 10;
1601 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
1602 MYLOGE("killing dumpstateBoard timed out after %zus, continue and "
1603 "there might be racing in content\n", killing_timeout_sec);
1604 }
1605
1606 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
1607 for (size_t i = 0; i < paths.size(); i++) {
1608 struct stat s;
1609 if (fstat(handle.get()->data[i], &s) == -1) {
1610 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(),
1611 strerror(errno));
1612 file_sizes[i] = -1;
1613 continue;
1614 }
1615 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001616 }
1617
1618 for (size_t i = 0; i < paths.size(); i++) {
1619 if (file_sizes[i] == -1) {
1620 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07001621 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001622 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07001623 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001624 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07001625 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001626 AddZipEntry(kDumpstateBoardFiles[i], paths[i]);
Jie Song9fbfad02017-06-20 16:29:42 -07001627 }
1628
Felipe Lemed8b94e52016-12-08 10:21:44 -08001629 printf("*** See dumpstate-board.txt entry ***\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001630}
1631
Nandana Dutt5fb117b2018-09-27 09:23:36 +01001632static void ShowUsageAndExit(int exit_code = 1) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001633 fprintf(stderr,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001634 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file] [-d] [-p] "
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001635 "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
1636 " -h: display this help message\n"
1637 " -b: play sound file instead of vibrate, at beginning of job\n"
1638 " -e: play sound file instead of vibrate, at end of job\n"
1639 " -o: write to file (instead of stdout)\n"
1640 " -d: append date to filename (requires -o)\n"
1641 " -p: capture screenshot to filename.png (requires -o)\n"
1642 " -z: generate zipped file (requires -o)\n"
1643 " -s: write output to control socket (for init)\n"
Takuya Ogawa47f644e2017-12-20 18:09:09 +09001644 " -S: write file location to control socket (for init; requires -o and -z)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001645 " -q: disable vibrate\n"
1646 " -B: send broadcast when finished (requires -o)\n"
1647 " -P: send broadcast when started and update system properties on "
1648 "progress (requires -o and -B)\n"
1649 " -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
1650 "shouldn't be used with -P)\n"
Felipe Lemed071c682016-10-20 16:48:00 -07001651 " -v: prints the dumpstate header and exit\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01001652 exit(exit_code);
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001653}
1654
1655static void ExitOnInvalidArgs() {
1656 fprintf(stderr, "invalid combination of args\n");
1657 ShowUsageAndExit();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001658}
1659
Wei Liuf87959e2016-08-26 14:51:42 -07001660static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07001661 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07001662}
1663
Felipe Leme1d486fe2016-10-14 18:06:47 -07001664bool Dumpstate::FinishZipFile() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001665 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07001666 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07001667 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001668 // Final timestamp
1669 char date[80];
1670 time_t the_real_now_please_stand_up = time(nullptr);
1671 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07001672 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001673 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001674
Felipe Leme9a523ae2016-10-20 15:10:33 -07001675 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001676 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08001677 return false;
1678 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07001679 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001680 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08001681 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08001682 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08001683
Felipe Leme0f3fb202016-06-10 17:10:53 -07001684 // Add log file (which contains stderr output) to zip...
1685 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001686 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07001687 MYLOGE("Failed to add dumpstate log to .zip file\n");
1688 return false;
1689 }
1690 // ... and re-opens it for further logging.
Felipe Leme9a523ae2016-10-20 15:10:33 -07001691 redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()));
Felipe Leme0f3fb202016-06-10 17:10:53 -07001692 fprintf(stderr, "\n");
1693
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001694 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07001695 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001696 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001697 return false;
1698 }
1699
Felipe Leme1d486fe2016-10-14 18:06:47 -07001700 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
1701 ds.zip_file.reset(nullptr);
1702
Felipe Lemee9d2c542016-11-15 11:48:26 -08001703 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
1704 if (remove(tmp_path_.c_str()) != 0) {
1705 MYLOGE("Failed to remove temporary file (%s): %s\n", tmp_path_.c_str(), strerror(errno));
Felipe Lemec4eee562016-04-21 15:42:55 -07001706 }
1707
Felipe Leme1e9edc62015-12-21 16:02:13 -08001708 return true;
1709}
Felipe Leme6e01fa62015-11-11 19:35:14 -08001710
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -07001711static std::string SHA256_file_hash(const std::string& filepath) {
Andreas Gampe27cd7b22016-07-18 18:24:05 -07001712 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK
1713 | O_CLOEXEC | O_NOFOLLOW)));
Andreas Gampeaff68432016-07-18 18:01:27 -07001714 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001715 MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
Yi Kong19d5c002018-07-20 13:39:55 -07001716 return nullptr;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001717 }
1718
1719 SHA256_CTX ctx;
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001720 SHA256_Init(&ctx);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001721
1722 std::vector<uint8_t> buffer(65536);
1723 while (1) {
1724 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
1725 if (bytes_read == 0) {
1726 break;
1727 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001728 MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
Yi Kong19d5c002018-07-20 13:39:55 -07001729 return nullptr;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001730 }
1731
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001732 SHA256_Update(&ctx, buffer.data(), bytes_read);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001733 }
1734
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001735 uint8_t hash[SHA256_DIGEST_LENGTH];
1736 SHA256_Final(hash, &ctx);
1737
1738 char hash_buffer[SHA256_DIGEST_LENGTH * 2 + 1];
1739 for(size_t i = 0; i < SHA256_DIGEST_LENGTH; i++) {
Michal Karpinskicbbdf732016-01-07 20:45:02 +00001740 sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001741 }
1742 hash_buffer[sizeof(hash_buffer) - 1] = 0;
1743 return std::string(hash_buffer);
1744}
1745
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001746static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) {
1747 // clang-format off
1748 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0",
1749 "--receiver-foreground", "--receiver-include-background", "-a", action};
1750 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08001751
1752 am.insert(am.end(), args.begin(), args.end());
1753
Felipe Leme8d2410e2017-02-08 09:46:08 -08001754 RunCommand("", am,
1755 CommandOptions::WithTimeout(20)
1756 .Log("Sending broadcast: '%s'\n")
1757 .Always()
1758 .DropRoot()
1759 .RedirectStderr()
1760 .Build());
1761}
1762
Felipe Leme35b8cf12017-02-10 15:47:29 -08001763static void Vibrate(int duration_ms) {
1764 // clang-format off
1765 RunCommand("", {"cmd", "vibrator", "vibrate", std::to_string(duration_ms), "dumpstate"},
1766 CommandOptions::WithTimeout(10)
1767 .Log("Vibrate: '%s'\n")
1768 .Always()
1769 .Build());
1770 // clang-format on
1771}
1772
Nandana Dutt4be45d12018-09-26 15:04:23 +01001773/*
1774 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
1775 * if we are writing zip files and adds the version file.
1776 */
1777static void PrepareToWriteToFile() {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01001778 ds.bugreport_dir_ = dirname(ds.options_->use_outfile.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01001779 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
1780 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01001781 ds.base_name_ =
1782 android::base::StringPrintf("%s-%s-%s", basename(ds.options_->use_outfile.c_str()),
1783 device_name.c_str(), build_id.c_str());
1784 if (ds.options_->do_add_date) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01001785 char date[80];
1786 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
1787 ds.name_ = date;
1788 } else {
1789 ds.name_ = "undated";
1790 }
1791
Nandana Dutt5fb117b2018-09-27 09:23:36 +01001792 if (ds.options_->telephony_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01001793 ds.base_name_ += "-telephony";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01001794 } else if (ds.options_->wifi_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01001795 ds.base_name_ += "-wifi";
1796 }
1797
Nandana Dutt5fb117b2018-09-27 09:23:36 +01001798 if (ds.options_->do_fb) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01001799 ds.screenshot_path_ = ds.GetPath(".png");
1800 }
1801 ds.tmp_path_ = ds.GetPath(".tmp");
1802 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
1803
1804 MYLOGD(
1805 "Bugreport dir: %s\n"
1806 "Base name: %s\n"
1807 "Suffix: %s\n"
1808 "Log path: %s\n"
1809 "Temporary path: %s\n"
1810 "Screenshot path: %s\n",
1811 ds.bugreport_dir_.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
1812 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
1813
Nandana Dutt5fb117b2018-09-27 09:23:36 +01001814 if (ds.options_->do_zip_file) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01001815 ds.path_ = ds.GetPath(".zip");
1816 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
1817 create_parent_dirs(ds.path_.c_str());
1818 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
1819 if (ds.zip_file == nullptr) {
1820 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
1821 } else {
1822 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
1823 }
1824 ds.AddTextZipEntry("version.txt", ds.version_);
1825 }
1826}
1827
1828/*
1829 * Finalizes writing to the file by renaming or zipping the tmp file to the final location,
1830 * printing zipped file status, etc.
1831 */
1832static void FinalizeFile() {
Nandana Dutt4be45d12018-09-26 15:04:23 +01001833 /* check if user changed the suffix using system properties */
1834 std::string name =
1835 android::base::GetProperty(android::base::StringPrintf("dumpstate.%d.name", ds.pid_), "");
1836 bool change_suffix = false;
1837 if (!name.empty()) {
1838 /* must whitelist which characters are allowed, otherwise it could cross directories */
1839 std::regex valid_regex("^[-_a-zA-Z0-9]+$");
1840 if (std::regex_match(name.c_str(), valid_regex)) {
1841 change_suffix = true;
1842 } else {
1843 MYLOGE("invalid suffix provided by user: %s\n", name.c_str());
1844 }
1845 }
1846 if (change_suffix) {
1847 MYLOGI("changing suffix from %s to %s\n", ds.name_.c_str(), name.c_str());
1848 ds.name_ = name;
1849 if (!ds.screenshot_path_.empty()) {
1850 std::string new_screenshot_path = ds.GetPath(".png");
1851 if (rename(ds.screenshot_path_.c_str(), new_screenshot_path.c_str())) {
1852 MYLOGE("rename(%s, %s): %s\n", ds.screenshot_path_.c_str(),
1853 new_screenshot_path.c_str(), strerror(errno));
1854 } else {
1855 ds.screenshot_path_ = new_screenshot_path;
1856 }
1857 }
1858 }
1859
1860 bool do_text_file = true;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01001861 if (ds.options_->do_zip_file) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01001862 if (!ds.FinishZipFile()) {
1863 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
1864 do_text_file = true;
1865 } else {
1866 do_text_file = false;
1867 // Since zip file is already created, it needs to be renamed.
1868 std::string new_path = ds.GetPath(".zip");
1869 if (ds.path_ != new_path) {
1870 MYLOGD("Renaming zip file from %s to %s\n", ds.path_.c_str(), new_path.c_str());
1871 if (rename(ds.path_.c_str(), new_path.c_str())) {
1872 MYLOGE("rename(%s, %s): %s\n", ds.path_.c_str(), new_path.c_str(),
1873 strerror(errno));
1874 } else {
1875 ds.path_ = new_path;
1876 }
1877 }
1878 }
1879 }
1880 if (do_text_file) {
1881 ds.path_ = ds.GetPath(".txt");
1882 MYLOGD("Generating .txt bugreport at %s from %s\n", ds.path_.c_str(), ds.tmp_path_.c_str());
1883 if (rename(ds.tmp_path_.c_str(), ds.path_.c_str())) {
1884 MYLOGE("rename(%s, %s): %s\n", ds.tmp_path_.c_str(), ds.path_.c_str(), strerror(errno));
1885 ds.path_.clear();
1886 }
1887 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01001888 if (ds.options_->use_control_socket) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01001889 if (do_text_file) {
1890 dprintf(ds.control_socket_fd_,
1891 "FAIL:could not create zip file, check %s "
1892 "for more details\n",
1893 ds.log_path_.c_str());
1894 } else {
1895 dprintf(ds.control_socket_fd_, "OK:%s\n", ds.path_.c_str());
1896 }
1897 }
1898}
1899
1900/* Broadcasts that we are done with the bugreport */
1901static void SendBugreportFinishedBroadcast() {
Nandana Dutt4be45d12018-09-26 15:04:23 +01001902 if (!ds.path_.empty()) {
1903 MYLOGI("Final bugreport path: %s\n", ds.path_.c_str());
1904 // clang-format off
1905
1906 std::vector<std::string> am_args = {
1907 "--receiver-permission", "android.permission.DUMP",
1908 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
1909 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
1910 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
1911 "--es", "android.intent.extra.BUGREPORT", ds.path_,
1912 "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_
1913 };
1914 // clang-format on
Nandana Dutt5fb117b2018-09-27 09:23:36 +01001915 if (ds.options_->do_fb) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01001916 am_args.push_back("--es");
1917 am_args.push_back("android.intent.extra.SCREENSHOT");
1918 am_args.push_back(ds.screenshot_path_);
1919 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01001920 if (ds.options_->notification_title.empty()) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01001921 am_args.push_back("--es");
1922 am_args.push_back("android.intent.extra.TITLE");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01001923 am_args.push_back(ds.options_->notification_title);
1924 if (!ds.options_->notification_description.empty()) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01001925 am_args.push_back("--es");
1926 am_args.push_back("android.intent.extra.DESCRIPTION");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01001927 am_args.push_back(ds.options_->notification_description);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001928 }
1929 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01001930 if (ds.options_->is_remote_mode) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01001931 am_args.push_back("--es");
1932 am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
1933 am_args.push_back(SHA256_file_hash(ds.path_));
1934 SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED", am_args);
1935 } else {
1936 SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args);
1937 }
1938 } else {
1939 MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
1940 }
1941}
1942
Nandana Dutt5fb117b2018-09-27 09:23:36 +01001943// TODO: Move away from system properties when we have options passed via binder calls.
1944/* Sets runtime options from the system properties and then clears those properties. */
1945static void SetOptionsFromProperties(Dumpstate::DumpOptions* options) {
1946 options->extra_options = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
1947 if (!options->extra_options.empty()) {
1948 // Framework uses a system property to override some command-line args.
1949 // Currently, it contains the type of the requested bugreport.
1950 if (options->extra_options == "bugreportplus") {
1951 // Currently, the dumpstate binder is only used by Shell to update progress.
1952 options->do_start_service = true;
1953 options->do_progress_updates = true;
1954 options->do_fb = false;
1955 } else if (options->extra_options == "bugreportremote") {
1956 options->do_vibrate = false;
1957 options->is_remote_mode = true;
1958 options->do_fb = false;
1959 } else if (options->extra_options == "bugreportwear") {
1960 options->do_start_service = true;
1961 options->do_progress_updates = true;
1962 options->do_zip_file = true;
1963 } else if (options->extra_options == "bugreporttelephony") {
1964 options->telephony_only = true;
1965 } else if (options->extra_options == "bugreportwifi") {
1966 options->wifi_only = true;
1967 options->do_zip_file = true;
1968 } else {
1969 MYLOGE("Unknown extra option: %s\n", options->extra_options.c_str());
1970 }
1971 // Reset the property
1972 android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, "");
1973 }
1974
1975 options->notification_title = android::base::GetProperty(PROPERTY_EXTRA_TITLE, "");
1976 if (!options->notification_title.empty()) {
1977 // Reset the property
1978 android::base::SetProperty(PROPERTY_EXTRA_TITLE, "");
1979
1980 options->extra_options = android::base::GetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
1981 if (!options->notification_description.empty()) {
1982 // Reset the property
1983 android::base::SetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
1984 }
1985 MYLOGD("notification (title: %s, description: %s)\n", options->notification_title.c_str(),
1986 options->notification_description.c_str());
1987 }
1988}
1989
1990Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
1991 RunStatus status = RunStatus::OK;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01001992 int c;
1993 while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
1994 switch (c) {
1995 // clang-format off
Nandana Dutt5fb117b2018-09-27 09:23:36 +01001996 case 'd': do_add_date = true; break;
1997 case 'z': do_zip_file = true; break;
1998 case 'o': use_outfile = optarg; break;
1999 case 's': use_socket = true; break;
2000 case 'S': use_control_socket = true; break;
2001 case 'v': show_header_only = true; break;
2002 case 'q': do_vibrate = false; break;
2003 case 'p': do_fb = true; break;
2004 case 'P': do_progress_updates = true; break;
2005 case 'R': is_remote_mode = true; break;
2006 case 'B': do_broadcast = true; break;
2007 case 'V': break; // compatibility no-op
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002008 case 'h':
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002009 status = RunStatus::HELP;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002010 break;
2011 default:
2012 fprintf(stderr, "Invalid option: %c\n", c);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002013 status = RunStatus::INVALID_INPUT;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002014 break;
2015 // clang-format on
2016 }
2017 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08002018
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002019 // TODO: use helper function to convert argv into a string
2020 for (int i = 0; i < argc; i++) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002021 args += argv[i];
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002022 if (i < argc - 1) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002023 args += " ";
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002024 }
2025 }
2026
2027 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
2028 optind = 1;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002029
2030 SetOptionsFromProperties(this);
2031 return status;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002032}
2033
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002034bool Dumpstate::DumpOptions::ValidateOptions() const {
2035 if ((do_zip_file || do_add_date || do_progress_updates || do_broadcast)
2036 && use_outfile.empty()) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002037 return false;
2038 }
2039
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002040 if (use_control_socket && !do_zip_file) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002041 return false;
2042 }
2043
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002044 if (do_progress_updates && !do_broadcast) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002045 return false;
2046 }
2047
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002048 if (is_remote_mode && (do_progress_updates || !do_broadcast || !do_zip_file || !do_add_date)) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002049 return false;
2050 }
2051 return true;
2052}
2053
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002054Dumpstate::RunStatus Dumpstate::RunWithOptions(std::unique_ptr<DumpOptions> options) {
2055 if (!options->ValidateOptions()) {
2056 return RunStatus::INVALID_INPUT;
2057 }
2058 options_ = std::move(options);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002059 /* set as high priority, and protect from OOM killer */
2060 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002061
Felipe Lemed071c682016-10-20 16:48:00 -07002062 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002063 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002064 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002065 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002066 } else {
2067 /* fallback to kernels <= 2.6.35 */
2068 oom_adj = fopen("/proc/self/oom_adj", "we");
2069 if (oom_adj) {
2070 fputs("-17", oom_adj);
2071 fclose(oom_adj);
2072 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002073 }
2074
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002075 if (version_ == VERSION_DEFAULT) {
2076 version_ = VERSION_CURRENT;
Michal Karpinski4db754f2015-12-11 18:04:32 +00002077 }
2078
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002079 if (version_ != VERSION_CURRENT && version_ != VERSION_SPLIT_ANR) {
Vishnu Nair64afc022018-02-01 15:29:34 -08002080 MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s')\n",
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002081 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
Vishnu Nair64afc022018-02-01 15:29:34 -08002082 VERSION_SPLIT_ANR.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002083 return RunStatus::INVALID_INPUT;
Felipe Lemed071c682016-10-20 16:48:00 -07002084 }
2085
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002086 if (options_->show_header_only) {
2087 PrintHeader();
2088 return RunStatus::OK;
Felipe Lemed071c682016-10-20 16:48:00 -07002089 }
2090
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002091 // Redirect output if needed
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002092 bool is_redirecting = !options_->use_socket && !options_->use_outfile.empty();
Felipe Leme7447d7c2016-11-03 18:12:22 -07002093
2094 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002095 std::string stats_path =
2096 is_redirecting ? android::base::StringPrintf("%s/dumpstate-stats.txt",
2097 dirname(options_->use_outfile.c_str()))
2098 : "";
2099 progress_.reset(new Progress(stats_path));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002100
Felipe Lemed071c682016-10-20 16:48:00 -07002101 /* gets the sequential id */
Felipe Leme7447d7c2016-11-03 18:12:22 -07002102 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002103 id_ = ++last_id;
Felipe Lemed071c682016-10-20 16:48:00 -07002104 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
2105
2106 MYLOGI("begin\n");
2107
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08002108 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07002109
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002110 if (options_->do_start_service) {
Felipe Leme75876a22016-10-27 16:31:27 -07002111 MYLOGI("Starting 'dumpstate' service\n");
2112 android::status_t ret;
2113 if ((ret = android::os::DumpstateService::Start()) != android::OK) {
2114 MYLOGE("Unable to start DumpstateService: %d\n", ret);
2115 }
2116 }
2117
Felipe Lemef0292972016-11-22 13:57:05 -08002118 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07002119 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
2120 }
2121
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002122 MYLOGI("dumpstate info: id=%d, args='%s', extra_options= %s)\n", id_, options_->args.c_str(),
2123 options_->extra_options.c_str());
Felipe Lemed071c682016-10-20 16:48:00 -07002124
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002125 MYLOGI("bugreport format version: %s\n", version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08002126
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002127 do_early_screenshot_ = options_->do_progress_updates;
Felipe Lemee338bf62015-12-07 14:03:50 -08002128
Christopher Ferrised9354f2014-10-01 17:35:01 -07002129 // If we are going to use a socket, do it as early as possible
2130 // to avoid timeouts from bugreport.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002131 if (options_->use_socket) {
Christopher Ferrised9354f2014-10-01 17:35:01 -07002132 redirect_to_socket(stdout, "dumpstate");
2133 }
2134
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002135 if (options_->use_control_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07002136 MYLOGD("Opening control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002137 control_socket_fd_ = open_socket("dumpstate");
2138 options_->do_progress_updates = 1;
Felipe Leme2628e9e2016-04-12 16:36:51 -07002139 }
2140
Felipe Leme71bbfc52015-11-23 14:14:51 -08002141 if (is_redirecting) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002142 PrepareToWriteToFile();
Felipe Leme1e9edc62015-12-21 16:02:13 -08002143
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002144 if (options_->do_progress_updates) {
2145 if (options_->do_broadcast) {
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07002146 // clang-format off
2147 std::vector<std::string> am_args = {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002148 "--receiver-permission", "android.permission.DUMP",
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002149 "--es", "android.intent.extra.NAME", name_,
2150 "--ei", "android.intent.extra.ID", std::to_string(id_),
2151 "--ei", "android.intent.extra.PID", std::to_string(pid_),
2152 "--ei", "android.intent.extra.MAX", std::to_string(progress_->GetMax()),
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07002153 };
2154 // clang-format on
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002155 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07002156 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002157 if (options_->use_control_socket) {
2158 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07002159 }
Felipe Leme71bbfc52015-11-23 14:14:51 -08002160 }
2161 }
2162
Nick Kralevichf3599b32016-01-25 15:05:16 -08002163 /* read /proc/cmdline before dropping root */
2164 FILE *cmdline = fopen("/proc/cmdline", "re");
2165 if (cmdline) {
2166 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
2167 fclose(cmdline);
2168 }
2169
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002170 if (options_->do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08002171 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05002172 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002173
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002174 if (options_->do_fb && do_early_screenshot_) {
2175 if (screenshot_path_.empty()) {
Felipe Leme3634a1e2015-12-09 10:11:47 -08002176 // should not have happened
Felipe Lemecbce55d2016-02-08 09:53:18 -08002177 MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
Felipe Leme3634a1e2015-12-09 10:11:47 -08002178 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002179 MYLOGI("taking early screenshot\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002180 TakeScreenshot();
Felipe Lemee338bf62015-12-07 14:03:50 -08002181 }
2182 }
2183
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002184 if (options_->do_zip_file && zip_file != nullptr) {
2185 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
2186 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07002187 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002188 }
2189 }
2190
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002191 int dup_stdout_fd;
2192 int dup_stderr_fd;
Felipe Leme71bbfc52015-11-23 14:14:51 -08002193 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002194 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002195 redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()));
2196 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
2197 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
2198 strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08002199 }
Vishnu Nair20cf5032018-01-05 13:15:49 -08002200 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
Felipe Leme6e01fa62015-11-11 19:35:14 -08002201 /* TODO: rather than generating a text file now and zipping it later,
2202 it would be more efficient to redirect stdout to the zip entry
2203 directly, but the libziparchive doesn't support that option yet. */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002204 redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()));
2205 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Leme6fe9db62016-02-12 09:04:16 -08002206 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002207 tmp_path_.c_str(), strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08002208 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002209 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08002210
2211 // Don't buffer stdout
2212 setvbuf(stdout, nullptr, _IONBF, 0);
2213
Felipe Leme608385d2016-02-01 10:35:38 -08002214 // NOTE: there should be no stdout output until now, otherwise it would break the header.
2215 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08002216 // duration is logged into MYLOG instead.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002217 PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07002218
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002219 if (options_->telephony_only) {
Jayachandran Ca94c7172017-06-10 15:08:12 -07002220 DumpstateTelephonyOnly();
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002221 DumpstateBoard();
2222 } else if (options_->wifi_only) {
mukesh agrawal253dad42018-01-23 21:59:59 -08002223 DumpstateWifiOnly();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002224 } else {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002225 // Dump state for the default case. This also drops root.
2226 if (!DumpstateDefault()) {
2227 // Something went wrong.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002228 return RunStatus::ERROR;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002229 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07002230 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07002231
Felipe Leme55b42a62015-11-10 17:39:08 -08002232 /* close output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08002233 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002234 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07002235 }
2236
Felipe Leme6e01fa62015-11-11 19:35:14 -08002237 /* rename or zip the (now complete) .tmp file to its final location */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002238 if (!options_->use_outfile.empty()) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002239 FinalizeFile();
Colin Crossf45fa6b2012-03-26 12:38:26 -07002240 }
2241
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002242 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002243 if (options_->do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09002244 for (int i = 0; i < 3; i++) {
2245 Vibrate(75);
2246 usleep((75 + 50) * 1000);
2247 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002248 }
2249
Jeff Brown1dc94e32014-09-11 14:15:27 -07002250 /* tell activity manager we're done */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002251 if (options_->do_broadcast) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002252 SendBugreportFinishedBroadcast();
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07002253 }
2254
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002255 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
2256 progress_->GetInitialMax());
2257 progress_->Save();
2258 MYLOGI("done (id %d)\n", id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002259
Felipe Leme107a05f2016-03-08 15:11:15 -08002260 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002261 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08002262 }
2263
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002264 if (options_->use_control_socket && control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07002265 MYLOGD("Closing control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002266 close(control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07002267 }
2268
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002269 tombstone_data_.clear();
2270 anr_data_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01002271
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002272 return RunStatus::OK;
2273}
2274
2275/* Main entry point for dumpstate. */
2276int run_main(int argc, char* argv[]) {
2277 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
2278 Dumpstate::RunStatus status = options->Initialize(argc, argv);
2279 if (status == Dumpstate::RunStatus::OK) {
2280 status = ds.RunWithOptions(std::move(options));
2281 }
2282
2283 switch (status) {
2284 case Dumpstate::RunStatus::OK:
2285 return 0;
2286 break;
2287 case Dumpstate::RunStatus::HELP:
2288 ShowUsageAndExit(0 /* exit code */);
2289 break;
2290 case Dumpstate::RunStatus::INVALID_INPUT:
2291 ExitOnInvalidArgs();
2292 break;
2293 case Dumpstate::RunStatus::ERROR:
2294 exit(-1);
2295 break;
2296 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002297 return 0;
2298}