blob: 69ced45ebbf0640c8bc5cbf8a5a903fbbfcb86fc [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
Makoto Onuki83ec63f2019-01-31 17:08:59 -0800940 RunCommand("ANR FILES", {"ls", "-lt", ANR_DIR});
941
Elliott Hughes69fe5ec2018-03-23 11:04:25 -0700942 // Slow traces for slow operations.
Felipe Lemee184f662016-10-27 10:04:47 -0700943 struct stat st;
Elliott Hughes69fe5ec2018-03-23 11:04:25 -0700944 int i = 0;
945 while (true) {
946 const std::string slow_trace_path =
947 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
948 if (stat(slow_trace_path.c_str(), &st)) {
949 // No traces file at this index, done with the files.
950 break;
Felipe Lemee184f662016-10-27 10:04:47 -0700951 }
Elliott Hughes69fe5ec2018-03-23 11:04:25 -0700952 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
953 i++;
Felipe Lemee184f662016-10-27 10:04:47 -0700954 }
955}
956
Wei Wang509bb5d2017-06-09 14:42:12 -0700957static void DumpBlockStatFiles() {
958 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -0700959
Wei Wang1dc1ef52017-06-12 11:28:37 -0700960 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
961
962 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -0700963 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
964 return;
965 }
966
967 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -0700968 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -0700969 if ((d->d_name[0] == '.')
970 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
971 || (d->d_name[1] == '\0'))) {
972 continue;
973 }
974 const std::string new_path =
975 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
976 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
977 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
978 printf("\n");
979 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700980 return;
Wei Wang509bb5d2017-06-09 14:42:12 -0700981}
Jayachandran Ca94c7172017-06-10 15:08:12 -0700982
983static void DumpPacketStats() {
984 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
985 DumpFile("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
986 DumpFile("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
987 DumpFile("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
988 DumpFile("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
989}
990
991static void DumpIpAddrAndRules() {
992 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
993 RunCommand("NETWORK INTERFACES", {"ip", "link"});
994 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
995 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
996 RunCommand("IP RULES", {"ip", "rule", "show"});
997 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
998}
999
Vishnu Nair64afc022018-02-01 15:29:34 -08001000static void RunDumpsysTextByPriority(const std::string& title, int priority,
1001 std::chrono::milliseconds timeout,
1002 std::chrono::milliseconds service_timeout) {
1003 auto start = std::chrono::steady_clock::now();
Vishnu Naire97d6122018-01-18 13:58:56 -08001004 sp<android::IServiceManager> sm = defaultServiceManager();
1005 Dumpsys dumpsys(sm.get());
Vishnu Naire97d6122018-01-18 13:58:56 -08001006 Vector<String16> args;
1007 Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
Vishnu Naire97d6122018-01-18 13:58:56 -08001008 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1009 for (const String16& service : services) {
1010 std::string path(title);
1011 path.append(" - ").append(String8(service).c_str());
1012 DumpstateSectionReporter section_reporter(path, ds.listener_, ds.report_section_);
1013 size_t bytes_written = 0;
1014 status_t status = dumpsys.startDumpThread(service, args);
1015 if (status == OK) {
1016 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1017 std::chrono::duration<double> elapsed_seconds;
1018 status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
1019 /* as_proto = */ false, elapsed_seconds, bytes_written);
1020 section_reporter.setSize(bytes_written);
1021 dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
1022 bool dump_complete = (status == OK);
1023 dumpsys.stopDumpThread(dump_complete);
1024 }
1025 section_reporter.setStatus(status);
1026
1027 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1028 std::chrono::steady_clock::now() - start);
1029 if (elapsed_duration > timeout) {
1030 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1031 elapsed_duration.count());
1032 break;
1033 }
1034 }
1035}
1036
Vishnu Nair64afc022018-02-01 15:29:34 -08001037static void RunDumpsysText(const std::string& title, int priority,
1038 std::chrono::milliseconds timeout,
1039 std::chrono::milliseconds service_timeout) {
1040 DurationReporter duration_reporter(title);
1041 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1042 fsync(STDOUT_FILENO);
1043 RunDumpsysTextByPriority(title, priority, timeout, service_timeout);
1044}
1045
1046/* Dump all services registered with Normal or Default priority. */
1047static void RunDumpsysTextNormalPriority(const std::string& title,
1048 std::chrono::milliseconds timeout,
1049 std::chrono::milliseconds service_timeout) {
1050 DurationReporter duration_reporter(title);
1051 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1052 fsync(STDOUT_FILENO);
1053 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout,
1054 service_timeout);
1055 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1056 service_timeout);
1057}
1058
1059static void RunDumpsysProto(const std::string& title, int priority,
1060 std::chrono::milliseconds timeout,
1061 std::chrono::milliseconds service_timeout) {
Luis Hector Chavez1e27b082018-03-22 15:36:42 -07001062 if (!ds.IsZipping()) {
1063 MYLOGD("Not dumping %s because it's not a zipped bugreport\n", title.c_str());
1064 return;
1065 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001066 sp<android::IServiceManager> sm = defaultServiceManager();
1067 Dumpsys dumpsys(sm.get());
1068 Vector<String16> args;
1069 Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
1070 DurationReporter duration_reporter(title);
1071
1072 auto start = std::chrono::steady_clock::now();
1073 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
1074 for (const String16& service : services) {
1075 std::string path(kProtoPath);
1076 path.append(String8(service).c_str());
1077 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
1078 path.append("_CRITICAL");
1079 } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
1080 path.append("_HIGH");
1081 }
1082 path.append(kProtoExt);
1083 DumpstateSectionReporter section_reporter(path, ds.listener_, ds.report_section_);
1084 status_t status = dumpsys.startDumpThread(service, args);
1085 if (status == OK) {
1086 status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
1087 bool dumpTerminated = (status == OK);
1088 dumpsys.stopDumpThread(dumpTerminated);
1089 }
1090 ZipWriter::FileEntry file_entry;
1091 ds.zip_writer_->GetLastEntry(&file_entry);
1092 section_reporter.setSize(file_entry.compressed_size);
1093 section_reporter.setStatus(status);
1094
1095 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1096 std::chrono::steady_clock::now() - start);
1097 if (elapsed_duration > timeout) {
1098 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1099 elapsed_duration.count());
1100 break;
1101 }
1102 }
1103}
1104
Vishnu Nair780b1282017-10-10 13:57:24 -07001105// Runs dumpsys on services that must dump first and and will take less than 100ms to dump.
1106static void RunDumpsysCritical() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001107 RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1108 /* timeout= */ 5s, /* service_timeout= */ 500ms);
1109 RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1110 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Vishnu Nair780b1282017-10-10 13:57:24 -07001111}
1112
1113// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
1114static void RunDumpsysHigh() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001115 // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
1116 // high priority. Reduce timeout once they are able to dump in a shorter time or
1117 // moved to a parallel task.
1118 RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1119 /* timeout= */ 90s, /* service_timeout= */ 30s);
1120 RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1121 /* timeout= */ 5s, /* service_timeout= */ 1s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001122}
1123
1124// Runs dumpsys on services that must dump but can take up to 10s to dump.
1125static void RunDumpsysNormal() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001126 RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
1127 RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1128 /* timeout= */ 90s, /* service_timeout= */ 10s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001129}
1130
Steven Moreland44cd9482018-01-04 16:24:13 -08001131static void DumpHals() {
Steven Moreland44cd9482018-01-04 16:24:13 -08001132 using android::hidl::manager::V1_0::IServiceManager;
1133 using android::hardware::defaultServiceManager;
1134
1135 sp<IServiceManager> sm = defaultServiceManager();
1136 if (sm == nullptr) {
1137 MYLOGE("Could not retrieve hwservicemanager to dump hals.\n");
1138 return;
1139 }
1140
1141 auto ret = sm->list([&](const auto& interfaces) {
1142 for (const std::string& interface : interfaces) {
1143 std::string cleanName = interface;
1144 std::replace_if(cleanName.begin(),
1145 cleanName.end(),
1146 [](char c) {
1147 return !isalnum(c) &&
1148 std::string("@-_:.").find(c) == std::string::npos;
1149 }, '_');
1150 const std::string path = kDumpstateBoardPath + "lshal_debug_" + cleanName;
1151
1152 {
1153 auto fd = android::base::unique_fd(
1154 TEMP_FAILURE_RETRY(open(path.c_str(),
1155 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1156 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1157 if (fd < 0) {
1158 MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str());
1159 continue;
1160 }
1161 RunCommandToFd(fd,
1162 "",
Steven Morelandc81cd3c2018-01-18 14:36:26 -08001163 {"lshal", "debug", "-E", interface},
Steven Moreland44cd9482018-01-04 16:24:13 -08001164 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1165
1166 bool empty = 0 == lseek(fd, 0, SEEK_END);
1167 if (!empty) {
1168 ds.AddZipEntry("lshal-debug/" + cleanName + ".txt", path);
1169 }
1170 }
1171
1172 unlink(path.c_str());
1173 }
1174 });
1175
1176 if (!ret.isOk()) {
1177 MYLOGE("Could not list hals from hwservicemanager.\n");
1178 }
1179}
1180
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001181static void dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001182 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001183
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001184 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001185 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001186 DumpBlockStatFiles();
Mark Salyzyn8c8130e2015-12-09 11:21:28 -08001187 dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001188 DumpFile("MEMORY INFO", "/proc/meminfo");
1189 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001190 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Felipe Lemef0292972016-11-22 13:57:05 -08001191 RunCommand("PROCRANK", {"procrank"}, AS_ROOT_20);
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001192 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1193 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1194 DumpFile("SLAB INFO", "/proc/slabinfo");
1195 DumpFile("ZONEINFO", "/proc/zoneinfo");
1196 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1197 DumpFile("BUDDYINFO", "/proc/buddyinfo");
1198 DumpFile("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001199
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001200 DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources");
1201 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
1202 DumpFile("KERNEL SYNC", "/d/sync");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001203
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001204 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001205 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Felipe Lemef0292972016-11-22 13:57:05 -08001206 RunCommand("LIBRANK", {"librank"}, CommandOptions::AS_ROOT);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001207
Andreas Huber69ec3ac2017-03-23 09:47:51 -07001208 if (ds.IsZipping()) {
Yifan Hong90e8d8d2018-06-28 13:14:39 -07001209 RunCommand("HARDWARE HALS", {"lshal", "-lVSietrpc", "--types=b,c,l,z"},
1210 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
Steven Moreland44cd9482018-01-04 16:24:13 -08001211 DumpHals();
Andreas Huber69ec3ac2017-03-23 09:47:51 -07001212 } else {
Yifan Hong90e8d8d2018-06-28 13:14:39 -07001213 RunCommand("HARDWARE HALS", {"lshal", "-lVSietrpc", "--types=b,c,l,z", "--debug"},
1214 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
Andreas Huber69ec3ac2017-03-23 09:47:51 -07001215 }
Steven Moreland81b429e2017-01-31 19:50:46 -08001216
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001217 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001218 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001219 struct stat s;
1220 if (stat("/proc/modules", &s) != 0) {
1221 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1222 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001223 RunCommand("LSMOD", {"lsmod"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001224 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001225
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001226 if (__android_logger_property_get_bool(
1227 "ro.logd.kernel", BOOL_DEFAULT_TRUE | BOOL_DEFAULT_FLAG_ENG | BOOL_DEFAULT_FLAG_SVELTE)) {
1228 DoKernelLogcat();
1229 } else {
1230 do_dmesg();
1231 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001232
Felipe Lemef0292972016-11-22 13:57:05 -08001233 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Jeff Brown1dc94e32014-09-11 14:15:27 -07001234 for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES");
1235 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001236 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001237
Ajay Panicker2ff8e872017-04-27 14:04:32 -07001238 /* Dump Bluetooth HCI logs */
1239 ds.AddDir("/data/misc/bluetooth/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001240
Felipe Leme9a523ae2016-10-20 15:10:33 -07001241 if (!ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001242 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001243 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001244 }
1245
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001246 DoLogcat();
Mark Salyzynecc07632015-07-30 14:57:09 -07001247
Felipe Lemee184f662016-10-27 10:04:47 -07001248 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001249
Narayan Kamath8f788292017-05-25 13:20:39 +01001250 // NOTE: tombstones are always added as separate entries in the zip archive
1251 // and are not interspersed with the main report.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001252 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
Narayan Kamathbd863722017-06-01 18:50:12 +01001253 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001254 if (!tombstones_dumped) {
1255 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001256 }
1257
Jayachandran Ca94c7172017-06-10 15:08:12 -07001258 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001259
Chenbo Feng276a3b62018-08-07 11:44:49 -07001260 RunDumpsys("EBPF MAP STATS", {"netd", "trafficcontroller"});
1261
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001262 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001263
Jayachandran Ca94c7172017-06-10 15:08:12 -07001264 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001265
1266 dump_route_tables();
1267
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001268 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1269 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1270 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001271
Vishnu Nair780b1282017-10-10 13:57:24 -07001272 RunDumpsysHigh();
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001273
Elliott Hughes23ccc622017-02-28 10:14:22 -08001274 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001275
Jin Qianf334d662017-10-10 14:41:37 -07001276 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001277
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001278 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001279
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001280 RunCommand("LAST RADIO LOG", {"parse_radio_log", "/proc/last_radio_log"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001281
Colin Crossf45fa6b2012-03-26 12:38:26 -07001282 /* Binder state is expensive to look at as it uses a lot of memory. */
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001283 DumpFile("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
1284 DumpFile("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
1285 DumpFile("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
1286 DumpFile("BINDER STATS", "/sys/kernel/debug/binder/stats");
1287 DumpFile("BINDER STATE", "/sys/kernel/debug/binder/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001288
Vishnu Nair36b4cdb2017-11-17 10:27:05 -08001289 /* Add window and surface trace files. */
1290 if (!PropertiesHelper::IsUserBuild()) {
1291 ds.AddDir(WMTRACE_DATA_DIR, false);
1292 }
1293
Felipe Leme6f674ae2016-11-18 17:10:33 -08001294 ds.DumpstateBoard();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001295
Steven Moreland7440ddb2016-12-15 16:13:39 -08001296 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001297 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1298 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001299 // su does not exist on user builds, so try running without it.
1300 // This way any implementations of vril-dump that do not require
1301 // root can run on user builds.
1302 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001303 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001304 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001305 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001306 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001307 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001308 }
1309
Felipe Lemed8b94e52016-12-08 10:21:44 -08001310 printf("========================================================\n");
1311 printf("== Android Framework Services\n");
1312 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001313
Vishnu Nair780b1282017-10-10 13:57:24 -07001314 RunDumpsysNormal();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001315
Felipe Lemed8b94e52016-12-08 10:21:44 -08001316 printf("========================================================\n");
1317 printf("== Checkins\n");
1318 printf("========================================================\n");
Dianne Hackborn02bea972013-06-26 18:59:09 -07001319
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001320 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1321 RunDumpsys("CHECKIN MEMINFO", {"meminfo", "--checkin"});
1322 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"});
1323 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"});
1324 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"});
1325 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"});
Dianne Hackborn02bea972013-06-26 18:59:09 -07001326
Felipe Lemed8b94e52016-12-08 10:21:44 -08001327 printf("========================================================\n");
1328 printf("== Running Application Activities\n");
1329 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001330
Makoto Onuki60780982018-04-16 15:34:00 -07001331 // The following dumpsys internally collects output from running apps, so it can take a long
1332 // time. So let's extend the timeout.
1333
1334 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1335
1336 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001337
Felipe Lemed8b94e52016-12-08 10:21:44 -08001338 printf("========================================================\n");
Makoto Onuki60780982018-04-16 15:34:00 -07001339 printf("== Running Application Services (platform)\n");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001340 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001341
Vishnu Nairc6e6ea72018-07-02 14:20:06 -07001342 RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
Makoto Onuki60780982018-04-16 15:34:00 -07001343 DUMPSYS_COMPONENTS_OPTIONS);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001344
Felipe Lemed8b94e52016-12-08 10:21:44 -08001345 printf("========================================================\n");
Makoto Onuki60780982018-04-16 15:34:00 -07001346 printf("== Running Application Services (non-platform)\n");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001347 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001348
Makoto Onuki60780982018-04-16 15:34:00 -07001349 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1350 DUMPSYS_COMPONENTS_OPTIONS);
1351
1352 printf("========================================================\n");
1353 printf("== Running Application Providers (platform)\n");
1354 printf("========================================================\n");
1355
1356 RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
1357 DUMPSYS_COMPONENTS_OPTIONS);
1358
1359 printf("========================================================\n");
1360 printf("== Running Application Providers (non-platform)\n");
1361 printf("========================================================\n");
1362
1363 RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1364 DUMPSYS_COMPONENTS_OPTIONS);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001365
Adrian Roos8b397ab2017-04-04 16:35:44 -07001366 printf("========================================================\n");
1367 printf("== Dropbox crashes\n");
1368 printf("========================================================\n");
1369
1370 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1371 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1372
Felipe Lemed8b94e52016-12-08 10:21:44 -08001373 printf("========================================================\n");
1374 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1375 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1376 printf("========================================================\n");
1377 printf("== dumpstate: done (id %d)\n", ds.id_);
1378 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001379}
1380
Nandana Dutt4be45d12018-09-26 15:04:23 +01001381/* Dumps state for the default case. Returns true if everything went fine. */
1382static bool DumpstateDefault() {
1383 // Dumps systrace right away, otherwise it will be filled with unnecessary events.
1384 // First try to dump anrd trace if the daemon is running. Otherwise, dump
1385 // the raw trace.
1386 if (!dump_anrd_trace()) {
1387 dump_systrace();
1388 }
1389
1390 // Invoking the following dumpsys calls before dump_traces() to try and
1391 // keep the system stats as close to its initial state as possible.
1392 RunDumpsysCritical();
1393
1394 /* collect stack traces from Dalvik and native processes (needs root) */
1395 dump_traces_path = dump_traces();
1396
1397 /* Run some operations that require root. */
1398 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping());
1399 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping());
1400
1401 ds.AddDir(RECOVERY_DIR, true);
1402 ds.AddDir(RECOVERY_DATA_DIR, true);
1403 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
1404 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1405 if (!PropertiesHelper::IsUserBuild()) {
1406 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1407 ds.AddDir(PROFILE_DATA_DIR_REF, true);
1408 }
1409 add_mountinfo();
1410 DumpIpTablesAsRoot();
1411
1412 // Capture any IPSec policies in play. No keys are exposed here.
1413 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1414
1415 // Run ss as root so we can see socket marks.
1416 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1417
1418 // Run iotop as root to show top 100 IO threads
1419 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1420
1421 if (!DropRootUser()) {
1422 return false;
1423 }
1424
1425 dumpstate();
1426 return true;
1427}
1428
mukesh agrawal253dad42018-01-23 21:59:59 -08001429// This method collects common dumpsys for telephony and wifi
1430static void DumpstateRadioCommon() {
Jayachandran Ca94c7172017-06-10 15:08:12 -07001431 DumpIpTablesAsRoot();
1432
1433 if (!DropRootUser()) {
1434 return;
1435 }
1436
1437 do_dmesg();
1438 DoLogcat();
1439 DumpPacketStats();
1440 DoKmsg();
1441 DumpIpAddrAndRules();
1442 dump_route_tables();
1443
1444 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
1445 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08001446}
1447
1448// This method collects dumpsys for telephony debugging only
1449static void DumpstateTelephonyOnly() {
1450 DurationReporter duration_reporter("DUMPSTATE");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001451 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
mukesh agrawal253dad42018-01-23 21:59:59 -08001452
1453 DumpstateRadioCommon();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001454
1455 RunCommand("SYSTEM PROPERTIES", {"getprop"});
1456
1457 printf("========================================================\n");
1458 printf("== Android Framework Services\n");
1459 printf("========================================================\n");
1460
Vishnu Nair652cc802017-11-30 15:18:30 -08001461 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1462 SEC_TO_MSEC(10));
1463 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
1464 SEC_TO_MSEC(10));
Amruth Ramachandrand25a9142018-04-02 16:16:09 -07001465 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
1466 SEC_TO_MSEC(10));
Sooraj Sasindrane8d98912018-04-20 11:31:55 -07001467 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
1468 SEC_TO_MSEC(10));
Jayachandran Ca94c7172017-06-10 15:08:12 -07001469
1470 printf("========================================================\n");
1471 printf("== Running Application Services\n");
1472 printf("========================================================\n");
1473
1474 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
1475
1476 printf("========================================================\n");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001477 printf("== Running Application Services (non-platform)\n");
1478 printf("========================================================\n");
1479
1480 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1481 DUMPSYS_COMPONENTS_OPTIONS);
1482
1483 printf("========================================================\n");
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07001484 printf("== Checkins\n");
1485 printf("========================================================\n");
1486
1487 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1488
1489 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07001490 printf("== dumpstate: done (id %d)\n", ds.id_);
1491 printf("========================================================\n");
1492}
1493
mukesh agrawal253dad42018-01-23 21:59:59 -08001494// This method collects dumpsys for wifi debugging only
1495static void DumpstateWifiOnly() {
1496 DurationReporter duration_reporter("DUMPSTATE");
1497
1498 DumpstateRadioCommon();
1499
1500 printf("========================================================\n");
1501 printf("== Android Framework Services\n");
1502 printf("========================================================\n");
1503
1504 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1505 SEC_TO_MSEC(10));
1506 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
1507 SEC_TO_MSEC(10));
1508
1509 printf("========================================================\n");
1510 printf("== dumpstate: done (id %d)\n", ds.id_);
1511 printf("========================================================\n");
1512}
1513
Felipe Leme6f674ae2016-11-18 17:10:33 -08001514void Dumpstate::DumpstateBoard() {
1515 DurationReporter duration_reporter("dumpstate_board()");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001516 printf("========================================================\n");
1517 printf("== Board\n");
1518 printf("========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001519
Felipe Leme6f674ae2016-11-18 17:10:33 -08001520 if (!IsZipping()) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08001521 MYLOGD("Not dumping board info because it's not a zipped bugreport\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001522 return;
1523 }
1524
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001525 std::vector<std::string> paths;
1526 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07001527 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001528 paths.emplace_back(kDumpstateBoardPath + kDumpstateBoardFiles[i]);
1529 remover.emplace_back(android::base::make_scope_guard(std::bind(
1530 [](std::string path) {
1531 if (remove(path.c_str()) != 0 && errno != ENOENT) {
1532 MYLOGE("Could not remove(%s): %s\n", path.c_str(), strerror(errno));
1533 }
1534 },
1535 paths[i])));
1536 }
Jie Song9fbfad02017-06-20 16:29:42 -07001537
Wei Wang587eac92018-04-05 12:17:20 -07001538 sp<IDumpstateDevice> dumpstate_device(IDumpstateDevice::getService());
1539 if (dumpstate_device == nullptr) {
1540 MYLOGE("No IDumpstateDevice implementation\n");
1541 return;
1542 }
1543
1544 using ScopedNativeHandle =
1545 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
1546 ScopedNativeHandle handle(native_handle_create(static_cast<int>(paths.size()), 0),
1547 [](native_handle_t* handle) {
1548 native_handle_close(handle);
1549 native_handle_delete(handle);
1550 });
1551 if (handle == nullptr) {
1552 MYLOGE("Could not create native_handle\n");
1553 return;
1554 }
1555
1556 for (size_t i = 0; i < paths.size(); i++) {
1557 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
1558
1559 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
1560 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1561 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1562 if (fd < 0) {
1563 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
1564 return;
1565 }
1566 handle.get()->data[i] = fd.release();
1567 }
1568
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001569 // Given that bugreport is required to diagnose failures, it's better to
Wei Wang587eac92018-04-05 12:17:20 -07001570 // set an arbitrary amount of timeout for IDumpstateDevice than to block the
1571 // rest of bugreport. In the timeout case, we will kill dumpstate board HAL
1572 // and grab whatever dumped
1573 std::packaged_task<bool()>
1574 dumpstate_task([paths, dumpstate_device, &handle]() -> bool {
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001575 android::hardware::Return<void> status = dumpstate_device->dumpstateBoard(handle.get());
1576 if (!status.isOk()) {
1577 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
Wei Wang587eac92018-04-05 12:17:20 -07001578 return false;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001579 }
Wei Wang587eac92018-04-05 12:17:20 -07001580 return true;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001581 });
Wei Wang587eac92018-04-05 12:17:20 -07001582
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001583 auto result = dumpstate_task.get_future();
1584 std::thread(std::move(dumpstate_task)).detach();
Wei Wang587eac92018-04-05 12:17:20 -07001585
1586 constexpr size_t timeout_sec = 30;
1587 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
1588 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate vendor HAL\n", timeout_sec);
1589 if (!android::base::SetProperty("ctl.interface_restart",
1590 android::base::StringPrintf("%s/default",
1591 IDumpstateDevice::descriptor))) {
1592 MYLOGE("Couldn't restart dumpstate HAL\n");
1593 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001594 }
Wei Wang587eac92018-04-05 12:17:20 -07001595 // Wait some time for init to kill dumpstate vendor HAL
1596 constexpr size_t killing_timeout_sec = 10;
1597 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
1598 MYLOGE("killing dumpstateBoard timed out after %zus, continue and "
1599 "there might be racing in content\n", killing_timeout_sec);
1600 }
1601
1602 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
1603 for (size_t i = 0; i < paths.size(); i++) {
1604 struct stat s;
1605 if (fstat(handle.get()->data[i], &s) == -1) {
1606 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(),
1607 strerror(errno));
1608 file_sizes[i] = -1;
1609 continue;
1610 }
1611 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001612 }
1613
1614 for (size_t i = 0; i < paths.size(); i++) {
1615 if (file_sizes[i] == -1) {
1616 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07001617 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001618 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07001619 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001620 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07001621 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001622 AddZipEntry(kDumpstateBoardFiles[i], paths[i]);
Jie Song9fbfad02017-06-20 16:29:42 -07001623 }
1624
Felipe Lemed8b94e52016-12-08 10:21:44 -08001625 printf("*** See dumpstate-board.txt entry ***\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001626}
1627
Nandana Dutt5fb117b2018-09-27 09:23:36 +01001628static void ShowUsageAndExit(int exit_code = 1) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001629 fprintf(stderr,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001630 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file] [-d] [-p] "
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001631 "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
1632 " -h: display this help message\n"
1633 " -b: play sound file instead of vibrate, at beginning of job\n"
1634 " -e: play sound file instead of vibrate, at end of job\n"
1635 " -o: write to file (instead of stdout)\n"
1636 " -d: append date to filename (requires -o)\n"
1637 " -p: capture screenshot to filename.png (requires -o)\n"
1638 " -z: generate zipped file (requires -o)\n"
1639 " -s: write output to control socket (for init)\n"
Takuya Ogawa47f644e2017-12-20 18:09:09 +09001640 " -S: write file location to control socket (for init; requires -o and -z)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001641 " -q: disable vibrate\n"
1642 " -B: send broadcast when finished (requires -o)\n"
1643 " -P: send broadcast when started and update system properties on "
1644 "progress (requires -o and -B)\n"
1645 " -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
1646 "shouldn't be used with -P)\n"
Felipe Lemed071c682016-10-20 16:48:00 -07001647 " -v: prints the dumpstate header and exit\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01001648 exit(exit_code);
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001649}
1650
1651static void ExitOnInvalidArgs() {
1652 fprintf(stderr, "invalid combination of args\n");
1653 ShowUsageAndExit();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001654}
1655
Wei Liuf87959e2016-08-26 14:51:42 -07001656static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07001657 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07001658}
1659
Felipe Leme1d486fe2016-10-14 18:06:47 -07001660bool Dumpstate::FinishZipFile() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001661 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07001662 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07001663 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001664 // Final timestamp
1665 char date[80];
1666 time_t the_real_now_please_stand_up = time(nullptr);
1667 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07001668 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001669 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001670
Felipe Leme9a523ae2016-10-20 15:10:33 -07001671 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001672 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08001673 return false;
1674 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07001675 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001676 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08001677 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08001678 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08001679
Felipe Leme0f3fb202016-06-10 17:10:53 -07001680 // Add log file (which contains stderr output) to zip...
1681 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001682 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07001683 MYLOGE("Failed to add dumpstate log to .zip file\n");
1684 return false;
1685 }
1686 // ... and re-opens it for further logging.
Felipe Leme9a523ae2016-10-20 15:10:33 -07001687 redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()));
Felipe Leme0f3fb202016-06-10 17:10:53 -07001688 fprintf(stderr, "\n");
1689
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001690 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07001691 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001692 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001693 return false;
1694 }
1695
Felipe Leme1d486fe2016-10-14 18:06:47 -07001696 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
1697 ds.zip_file.reset(nullptr);
1698
Felipe Lemee9d2c542016-11-15 11:48:26 -08001699 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
1700 if (remove(tmp_path_.c_str()) != 0) {
1701 MYLOGE("Failed to remove temporary file (%s): %s\n", tmp_path_.c_str(), strerror(errno));
Felipe Lemec4eee562016-04-21 15:42:55 -07001702 }
1703
Felipe Leme1e9edc62015-12-21 16:02:13 -08001704 return true;
1705}
Felipe Leme6e01fa62015-11-11 19:35:14 -08001706
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -07001707static std::string SHA256_file_hash(const std::string& filepath) {
Andreas Gampe27cd7b22016-07-18 18:24:05 -07001708 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK
1709 | O_CLOEXEC | O_NOFOLLOW)));
Andreas Gampeaff68432016-07-18 18:01:27 -07001710 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001711 MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
Yi Kong19d5c002018-07-20 13:39:55 -07001712 return nullptr;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001713 }
1714
1715 SHA256_CTX ctx;
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001716 SHA256_Init(&ctx);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001717
1718 std::vector<uint8_t> buffer(65536);
1719 while (1) {
1720 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
1721 if (bytes_read == 0) {
1722 break;
1723 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001724 MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
Yi Kong19d5c002018-07-20 13:39:55 -07001725 return nullptr;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001726 }
1727
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001728 SHA256_Update(&ctx, buffer.data(), bytes_read);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001729 }
1730
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001731 uint8_t hash[SHA256_DIGEST_LENGTH];
1732 SHA256_Final(hash, &ctx);
1733
1734 char hash_buffer[SHA256_DIGEST_LENGTH * 2 + 1];
1735 for(size_t i = 0; i < SHA256_DIGEST_LENGTH; i++) {
Michal Karpinskicbbdf732016-01-07 20:45:02 +00001736 sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001737 }
1738 hash_buffer[sizeof(hash_buffer) - 1] = 0;
1739 return std::string(hash_buffer);
1740}
1741
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001742static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) {
1743 // clang-format off
1744 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0",
1745 "--receiver-foreground", "--receiver-include-background", "-a", action};
1746 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08001747
1748 am.insert(am.end(), args.begin(), args.end());
1749
Felipe Leme8d2410e2017-02-08 09:46:08 -08001750 RunCommand("", am,
1751 CommandOptions::WithTimeout(20)
1752 .Log("Sending broadcast: '%s'\n")
1753 .Always()
1754 .DropRoot()
1755 .RedirectStderr()
1756 .Build());
1757}
1758
Felipe Leme35b8cf12017-02-10 15:47:29 -08001759static void Vibrate(int duration_ms) {
1760 // clang-format off
1761 RunCommand("", {"cmd", "vibrator", "vibrate", std::to_string(duration_ms), "dumpstate"},
1762 CommandOptions::WithTimeout(10)
1763 .Log("Vibrate: '%s'\n")
1764 .Always()
1765 .Build());
1766 // clang-format on
1767}
1768
Nandana Dutt4be45d12018-09-26 15:04:23 +01001769/*
1770 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
1771 * if we are writing zip files and adds the version file.
1772 */
1773static void PrepareToWriteToFile() {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01001774 ds.bugreport_dir_ = dirname(ds.options_->use_outfile.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01001775 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
1776 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01001777 ds.base_name_ =
1778 android::base::StringPrintf("%s-%s-%s", basename(ds.options_->use_outfile.c_str()),
1779 device_name.c_str(), build_id.c_str());
1780 if (ds.options_->do_add_date) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01001781 char date[80];
1782 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
1783 ds.name_ = date;
1784 } else {
1785 ds.name_ = "undated";
1786 }
1787
Nandana Dutt5fb117b2018-09-27 09:23:36 +01001788 if (ds.options_->telephony_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01001789 ds.base_name_ += "-telephony";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01001790 } else if (ds.options_->wifi_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01001791 ds.base_name_ += "-wifi";
1792 }
1793
Nandana Dutt5fb117b2018-09-27 09:23:36 +01001794 if (ds.options_->do_fb) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01001795 ds.screenshot_path_ = ds.GetPath(".png");
1796 }
1797 ds.tmp_path_ = ds.GetPath(".tmp");
1798 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
1799
1800 MYLOGD(
1801 "Bugreport dir: %s\n"
1802 "Base name: %s\n"
1803 "Suffix: %s\n"
1804 "Log path: %s\n"
1805 "Temporary path: %s\n"
1806 "Screenshot path: %s\n",
1807 ds.bugreport_dir_.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
1808 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
1809
Nandana Dutt5fb117b2018-09-27 09:23:36 +01001810 if (ds.options_->do_zip_file) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01001811 ds.path_ = ds.GetPath(".zip");
1812 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
1813 create_parent_dirs(ds.path_.c_str());
1814 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
1815 if (ds.zip_file == nullptr) {
1816 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
1817 } else {
1818 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
1819 }
1820 ds.AddTextZipEntry("version.txt", ds.version_);
1821 }
1822}
1823
1824/*
1825 * Finalizes writing to the file by renaming or zipping the tmp file to the final location,
1826 * printing zipped file status, etc.
1827 */
1828static void FinalizeFile() {
Nandana Dutt4be45d12018-09-26 15:04:23 +01001829 /* check if user changed the suffix using system properties */
1830 std::string name =
1831 android::base::GetProperty(android::base::StringPrintf("dumpstate.%d.name", ds.pid_), "");
1832 bool change_suffix = false;
1833 if (!name.empty()) {
1834 /* must whitelist which characters are allowed, otherwise it could cross directories */
1835 std::regex valid_regex("^[-_a-zA-Z0-9]+$");
1836 if (std::regex_match(name.c_str(), valid_regex)) {
1837 change_suffix = true;
1838 } else {
1839 MYLOGE("invalid suffix provided by user: %s\n", name.c_str());
1840 }
1841 }
1842 if (change_suffix) {
1843 MYLOGI("changing suffix from %s to %s\n", ds.name_.c_str(), name.c_str());
1844 ds.name_ = name;
1845 if (!ds.screenshot_path_.empty()) {
1846 std::string new_screenshot_path = ds.GetPath(".png");
1847 if (rename(ds.screenshot_path_.c_str(), new_screenshot_path.c_str())) {
1848 MYLOGE("rename(%s, %s): %s\n", ds.screenshot_path_.c_str(),
1849 new_screenshot_path.c_str(), strerror(errno));
1850 } else {
1851 ds.screenshot_path_ = new_screenshot_path;
1852 }
1853 }
1854 }
1855
1856 bool do_text_file = true;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01001857 if (ds.options_->do_zip_file) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01001858 if (!ds.FinishZipFile()) {
1859 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
1860 do_text_file = true;
1861 } else {
1862 do_text_file = false;
1863 // Since zip file is already created, it needs to be renamed.
1864 std::string new_path = ds.GetPath(".zip");
1865 if (ds.path_ != new_path) {
1866 MYLOGD("Renaming zip file from %s to %s\n", ds.path_.c_str(), new_path.c_str());
1867 if (rename(ds.path_.c_str(), new_path.c_str())) {
1868 MYLOGE("rename(%s, %s): %s\n", ds.path_.c_str(), new_path.c_str(),
1869 strerror(errno));
1870 } else {
1871 ds.path_ = new_path;
1872 }
1873 }
1874 }
1875 }
1876 if (do_text_file) {
1877 ds.path_ = ds.GetPath(".txt");
1878 MYLOGD("Generating .txt bugreport at %s from %s\n", ds.path_.c_str(), ds.tmp_path_.c_str());
1879 if (rename(ds.tmp_path_.c_str(), ds.path_.c_str())) {
1880 MYLOGE("rename(%s, %s): %s\n", ds.tmp_path_.c_str(), ds.path_.c_str(), strerror(errno));
1881 ds.path_.clear();
1882 }
1883 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01001884 if (ds.options_->use_control_socket) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01001885 if (do_text_file) {
1886 dprintf(ds.control_socket_fd_,
1887 "FAIL:could not create zip file, check %s "
1888 "for more details\n",
1889 ds.log_path_.c_str());
1890 } else {
1891 dprintf(ds.control_socket_fd_, "OK:%s\n", ds.path_.c_str());
1892 }
1893 }
1894}
1895
1896/* Broadcasts that we are done with the bugreport */
1897static void SendBugreportFinishedBroadcast() {
Nandana Dutt4be45d12018-09-26 15:04:23 +01001898 if (!ds.path_.empty()) {
1899 MYLOGI("Final bugreport path: %s\n", ds.path_.c_str());
1900 // clang-format off
1901
1902 std::vector<std::string> am_args = {
1903 "--receiver-permission", "android.permission.DUMP",
1904 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
1905 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
1906 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
1907 "--es", "android.intent.extra.BUGREPORT", ds.path_,
1908 "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_
1909 };
1910 // clang-format on
Nandana Dutt5fb117b2018-09-27 09:23:36 +01001911 if (ds.options_->do_fb) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01001912 am_args.push_back("--es");
1913 am_args.push_back("android.intent.extra.SCREENSHOT");
1914 am_args.push_back(ds.screenshot_path_);
1915 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01001916 if (ds.options_->notification_title.empty()) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01001917 am_args.push_back("--es");
1918 am_args.push_back("android.intent.extra.TITLE");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01001919 am_args.push_back(ds.options_->notification_title);
1920 if (!ds.options_->notification_description.empty()) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01001921 am_args.push_back("--es");
1922 am_args.push_back("android.intent.extra.DESCRIPTION");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01001923 am_args.push_back(ds.options_->notification_description);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001924 }
1925 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01001926 if (ds.options_->is_remote_mode) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01001927 am_args.push_back("--es");
1928 am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
1929 am_args.push_back(SHA256_file_hash(ds.path_));
1930 SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED", am_args);
1931 } else {
1932 SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args);
1933 }
1934 } else {
1935 MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
1936 }
1937}
1938
Nandana Dutt5fb117b2018-09-27 09:23:36 +01001939// TODO: Move away from system properties when we have options passed via binder calls.
1940/* Sets runtime options from the system properties and then clears those properties. */
1941static void SetOptionsFromProperties(Dumpstate::DumpOptions* options) {
1942 options->extra_options = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
1943 if (!options->extra_options.empty()) {
1944 // Framework uses a system property to override some command-line args.
1945 // Currently, it contains the type of the requested bugreport.
1946 if (options->extra_options == "bugreportplus") {
1947 // Currently, the dumpstate binder is only used by Shell to update progress.
1948 options->do_start_service = true;
1949 options->do_progress_updates = true;
1950 options->do_fb = false;
1951 } else if (options->extra_options == "bugreportremote") {
1952 options->do_vibrate = false;
1953 options->is_remote_mode = true;
1954 options->do_fb = false;
1955 } else if (options->extra_options == "bugreportwear") {
1956 options->do_start_service = true;
1957 options->do_progress_updates = true;
1958 options->do_zip_file = true;
1959 } else if (options->extra_options == "bugreporttelephony") {
1960 options->telephony_only = true;
1961 } else if (options->extra_options == "bugreportwifi") {
1962 options->wifi_only = true;
1963 options->do_zip_file = true;
1964 } else {
1965 MYLOGE("Unknown extra option: %s\n", options->extra_options.c_str());
1966 }
1967 // Reset the property
1968 android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, "");
1969 }
1970
1971 options->notification_title = android::base::GetProperty(PROPERTY_EXTRA_TITLE, "");
1972 if (!options->notification_title.empty()) {
1973 // Reset the property
1974 android::base::SetProperty(PROPERTY_EXTRA_TITLE, "");
1975
1976 options->extra_options = android::base::GetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
1977 if (!options->notification_description.empty()) {
1978 // Reset the property
1979 android::base::SetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
1980 }
1981 MYLOGD("notification (title: %s, description: %s)\n", options->notification_title.c_str(),
1982 options->notification_description.c_str());
1983 }
1984}
1985
1986Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
1987 RunStatus status = RunStatus::OK;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01001988 int c;
1989 while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
1990 switch (c) {
1991 // clang-format off
Nandana Dutt5fb117b2018-09-27 09:23:36 +01001992 case 'd': do_add_date = true; break;
1993 case 'z': do_zip_file = true; break;
1994 case 'o': use_outfile = optarg; break;
1995 case 's': use_socket = true; break;
1996 case 'S': use_control_socket = true; break;
1997 case 'v': show_header_only = true; break;
1998 case 'q': do_vibrate = false; break;
1999 case 'p': do_fb = true; break;
2000 case 'P': do_progress_updates = true; break;
2001 case 'R': is_remote_mode = true; break;
2002 case 'B': do_broadcast = true; break;
2003 case 'V': break; // compatibility no-op
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002004 case 'h':
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002005 status = RunStatus::HELP;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002006 break;
2007 default:
2008 fprintf(stderr, "Invalid option: %c\n", c);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002009 status = RunStatus::INVALID_INPUT;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002010 break;
2011 // clang-format on
2012 }
2013 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08002014
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002015 // TODO: use helper function to convert argv into a string
2016 for (int i = 0; i < argc; i++) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002017 args += argv[i];
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002018 if (i < argc - 1) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002019 args += " ";
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002020 }
2021 }
2022
2023 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
2024 optind = 1;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002025
2026 SetOptionsFromProperties(this);
2027 return status;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002028}
2029
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002030bool Dumpstate::DumpOptions::ValidateOptions() const {
2031 if ((do_zip_file || do_add_date || do_progress_updates || do_broadcast)
2032 && use_outfile.empty()) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002033 return false;
2034 }
2035
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002036 if (use_control_socket && !do_zip_file) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002037 return false;
2038 }
2039
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002040 if (do_progress_updates && !do_broadcast) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002041 return false;
2042 }
2043
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002044 if (is_remote_mode && (do_progress_updates || !do_broadcast || !do_zip_file || !do_add_date)) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002045 return false;
2046 }
2047 return true;
2048}
2049
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002050Dumpstate::RunStatus Dumpstate::RunWithOptions(std::unique_ptr<DumpOptions> options) {
2051 if (!options->ValidateOptions()) {
2052 return RunStatus::INVALID_INPUT;
2053 }
2054 options_ = std::move(options);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002055 /* set as high priority, and protect from OOM killer */
2056 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002057
Felipe Lemed071c682016-10-20 16:48:00 -07002058 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002059 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002060 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002061 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002062 } else {
2063 /* fallback to kernels <= 2.6.35 */
2064 oom_adj = fopen("/proc/self/oom_adj", "we");
2065 if (oom_adj) {
2066 fputs("-17", oom_adj);
2067 fclose(oom_adj);
2068 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002069 }
2070
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002071 if (version_ == VERSION_DEFAULT) {
2072 version_ = VERSION_CURRENT;
Michal Karpinski4db754f2015-12-11 18:04:32 +00002073 }
2074
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002075 if (version_ != VERSION_CURRENT && version_ != VERSION_SPLIT_ANR) {
Vishnu Nair64afc022018-02-01 15:29:34 -08002076 MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s')\n",
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002077 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
Vishnu Nair64afc022018-02-01 15:29:34 -08002078 VERSION_SPLIT_ANR.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002079 return RunStatus::INVALID_INPUT;
Felipe Lemed071c682016-10-20 16:48:00 -07002080 }
2081
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002082 if (options_->show_header_only) {
2083 PrintHeader();
2084 return RunStatus::OK;
Felipe Lemed071c682016-10-20 16:48:00 -07002085 }
2086
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002087 // Redirect output if needed
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002088 bool is_redirecting = !options_->use_socket && !options_->use_outfile.empty();
Felipe Leme7447d7c2016-11-03 18:12:22 -07002089
2090 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002091 std::string stats_path =
2092 is_redirecting ? android::base::StringPrintf("%s/dumpstate-stats.txt",
2093 dirname(options_->use_outfile.c_str()))
2094 : "";
2095 progress_.reset(new Progress(stats_path));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002096
Felipe Lemed071c682016-10-20 16:48:00 -07002097 /* gets the sequential id */
Felipe Leme7447d7c2016-11-03 18:12:22 -07002098 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002099 id_ = ++last_id;
Felipe Lemed071c682016-10-20 16:48:00 -07002100 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
2101
2102 MYLOGI("begin\n");
2103
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08002104 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07002105
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002106 if (options_->do_start_service) {
Felipe Leme75876a22016-10-27 16:31:27 -07002107 MYLOGI("Starting 'dumpstate' service\n");
2108 android::status_t ret;
2109 if ((ret = android::os::DumpstateService::Start()) != android::OK) {
2110 MYLOGE("Unable to start DumpstateService: %d\n", ret);
2111 }
2112 }
2113
Felipe Lemef0292972016-11-22 13:57:05 -08002114 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07002115 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
2116 }
2117
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002118 MYLOGI("dumpstate info: id=%d, args='%s', extra_options= %s)\n", id_, options_->args.c_str(),
2119 options_->extra_options.c_str());
Felipe Lemed071c682016-10-20 16:48:00 -07002120
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002121 MYLOGI("bugreport format version: %s\n", version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08002122
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002123 do_early_screenshot_ = options_->do_progress_updates;
Felipe Lemee338bf62015-12-07 14:03:50 -08002124
Christopher Ferrised9354f2014-10-01 17:35:01 -07002125 // If we are going to use a socket, do it as early as possible
2126 // to avoid timeouts from bugreport.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002127 if (options_->use_socket) {
Christopher Ferrised9354f2014-10-01 17:35:01 -07002128 redirect_to_socket(stdout, "dumpstate");
2129 }
2130
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002131 if (options_->use_control_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07002132 MYLOGD("Opening control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002133 control_socket_fd_ = open_socket("dumpstate");
2134 options_->do_progress_updates = 1;
Felipe Leme2628e9e2016-04-12 16:36:51 -07002135 }
2136
Felipe Leme71bbfc52015-11-23 14:14:51 -08002137 if (is_redirecting) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002138 PrepareToWriteToFile();
Felipe Leme1e9edc62015-12-21 16:02:13 -08002139
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002140 if (options_->do_progress_updates) {
2141 if (options_->do_broadcast) {
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07002142 // clang-format off
2143 std::vector<std::string> am_args = {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002144 "--receiver-permission", "android.permission.DUMP",
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002145 "--es", "android.intent.extra.NAME", name_,
2146 "--ei", "android.intent.extra.ID", std::to_string(id_),
2147 "--ei", "android.intent.extra.PID", std::to_string(pid_),
2148 "--ei", "android.intent.extra.MAX", std::to_string(progress_->GetMax()),
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07002149 };
2150 // clang-format on
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002151 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07002152 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002153 if (options_->use_control_socket) {
2154 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07002155 }
Felipe Leme71bbfc52015-11-23 14:14:51 -08002156 }
2157 }
2158
Nick Kralevichf3599b32016-01-25 15:05:16 -08002159 /* read /proc/cmdline before dropping root */
2160 FILE *cmdline = fopen("/proc/cmdline", "re");
2161 if (cmdline) {
2162 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
2163 fclose(cmdline);
2164 }
2165
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002166 if (options_->do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08002167 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05002168 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002169
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002170 if (options_->do_fb && do_early_screenshot_) {
2171 if (screenshot_path_.empty()) {
Felipe Leme3634a1e2015-12-09 10:11:47 -08002172 // should not have happened
Felipe Lemecbce55d2016-02-08 09:53:18 -08002173 MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
Felipe Leme3634a1e2015-12-09 10:11:47 -08002174 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002175 MYLOGI("taking early screenshot\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002176 TakeScreenshot();
Felipe Lemee338bf62015-12-07 14:03:50 -08002177 }
2178 }
2179
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002180 if (options_->do_zip_file && zip_file != nullptr) {
2181 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
2182 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07002183 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002184 }
2185 }
2186
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002187 int dup_stdout_fd;
2188 int dup_stderr_fd;
Felipe Leme71bbfc52015-11-23 14:14:51 -08002189 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002190 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002191 redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()));
2192 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
2193 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
2194 strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08002195 }
Vishnu Nair20cf5032018-01-05 13:15:49 -08002196 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
Felipe Leme6e01fa62015-11-11 19:35:14 -08002197 /* TODO: rather than generating a text file now and zipping it later,
2198 it would be more efficient to redirect stdout to the zip entry
2199 directly, but the libziparchive doesn't support that option yet. */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002200 redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()));
2201 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Leme6fe9db62016-02-12 09:04:16 -08002202 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002203 tmp_path_.c_str(), strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08002204 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002205 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08002206
2207 // Don't buffer stdout
2208 setvbuf(stdout, nullptr, _IONBF, 0);
2209
Felipe Leme608385d2016-02-01 10:35:38 -08002210 // NOTE: there should be no stdout output until now, otherwise it would break the header.
2211 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08002212 // duration is logged into MYLOG instead.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002213 PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07002214
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002215 if (options_->telephony_only) {
Jayachandran Ca94c7172017-06-10 15:08:12 -07002216 DumpstateTelephonyOnly();
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002217 DumpstateBoard();
2218 } else if (options_->wifi_only) {
mukesh agrawal253dad42018-01-23 21:59:59 -08002219 DumpstateWifiOnly();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002220 } else {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002221 // Dump state for the default case. This also drops root.
2222 if (!DumpstateDefault()) {
2223 // Something went wrong.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002224 return RunStatus::ERROR;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002225 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07002226 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07002227
Felipe Leme55b42a62015-11-10 17:39:08 -08002228 /* close output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08002229 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002230 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07002231 }
2232
Felipe Leme6e01fa62015-11-11 19:35:14 -08002233 /* rename or zip the (now complete) .tmp file to its final location */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002234 if (!options_->use_outfile.empty()) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002235 FinalizeFile();
Colin Crossf45fa6b2012-03-26 12:38:26 -07002236 }
2237
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002238 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002239 if (options_->do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09002240 for (int i = 0; i < 3; i++) {
2241 Vibrate(75);
2242 usleep((75 + 50) * 1000);
2243 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002244 }
2245
Jeff Brown1dc94e32014-09-11 14:15:27 -07002246 /* tell activity manager we're done */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002247 if (options_->do_broadcast) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002248 SendBugreportFinishedBroadcast();
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07002249 }
2250
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002251 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
2252 progress_->GetInitialMax());
2253 progress_->Save();
2254 MYLOGI("done (id %d)\n", id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002255
Felipe Leme107a05f2016-03-08 15:11:15 -08002256 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002257 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08002258 }
2259
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002260 if (options_->use_control_socket && control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07002261 MYLOGD("Closing control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002262 close(control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07002263 }
2264
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002265 tombstone_data_.clear();
2266 anr_data_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01002267
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002268 return RunStatus::OK;
2269}
2270
2271/* Main entry point for dumpstate. */
2272int run_main(int argc, char* argv[]) {
2273 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
2274 Dumpstate::RunStatus status = options->Initialize(argc, argv);
2275 if (status == Dumpstate::RunStatus::OK) {
2276 status = ds.RunWithOptions(std::move(options));
2277 }
2278
2279 switch (status) {
2280 case Dumpstate::RunStatus::OK:
2281 return 0;
2282 break;
2283 case Dumpstate::RunStatus::HELP:
2284 ShowUsageAndExit(0 /* exit code */);
2285 break;
2286 case Dumpstate::RunStatus::INVALID_INPUT:
2287 ExitOnInvalidArgs();
2288 break;
2289 case Dumpstate::RunStatus::ERROR:
2290 exit(-1);
2291 break;
2292 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002293 return 0;
2294}