blob: 10f252fb7e2a8593169d16561e72ae0f215d0f04 [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>
Narayan Kamath8f788292017-05-25 13:20:39 +010035#include <memory>
36#include <regex>
37#include <set>
38#include <string>
39#include <vector>
Colin Crossf45fa6b2012-03-26 12:38:26 -070040
Felipe Leme96c2bbb2016-09-26 09:21:21 -070041#include <android-base/file.h>
42#include <android-base/properties.h>
Elliott Hughes9dc117c2015-12-07 14:21:50 -080043#include <android-base/stringprintf.h>
Naveen Kalla058e1e82016-10-19 21:38:44 -070044#include <android-base/strings.h>
Andreas Gampeaff68432016-07-18 18:01:27 -070045#include <android-base/unique_fd.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080046#include <android/hardware/dumpstate/1.0/IDumpstateDevice.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080047#include <android/hidl/manager/1.0/IServiceManager.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080048#include <cutils/native_handle.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070049#include <cutils/properties.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080050#include <dumpsys.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080051#include <hidl/ServiceManagement.h>
Felipe Leme75876a22016-10-27 16:31:27 -070052#include <openssl/sha.h>
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070053#include <private/android_filesystem_config.h>
54#include <private/android_logger.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080055#include <serviceutils/PriorityDumper.h>
Felipe Lemef0292972016-11-22 13:57:05 -080056#include "DumpstateInternal.h"
Vishnu Naire97d6122018-01-18 13:58:56 -080057#include "DumpstateSectionReporter.h"
Felipe Leme75876a22016-10-27 16:31:27 -070058#include "DumpstateService.h"
Colin Crossf45fa6b2012-03-26 12:38:26 -070059#include "dumpstate.h"
Felipe Leme6e01fa62015-11-11 19:35:14 -080060
Steven Morelandcb7ef822016-11-29 13:20:37 -080061using ::android::hardware::dumpstate::V1_0::IDumpstateDevice;
Vishnu Naire97d6122018-01-18 13:58:56 -080062using ::std::literals::chrono_literals::operator""ms;
63using ::std::literals::chrono_literals::operator""s;
Steven Morelandcb7ef822016-11-29 13:20:37 -080064
Felipe Leme47e9be22016-12-21 15:37:07 -080065// TODO: remove once moved to namespace
Vishnu Naire97d6122018-01-18 13:58:56 -080066using android::defaultServiceManager;
67using android::Dumpsys;
68using android::INVALID_OPERATION;
69using android::IServiceManager;
70using android::OK;
71using android::sp;
72using android::status_t;
73using android::String16;
74using android::String8;
75using android::TIMED_OUT;
76using android::UNKNOWN_ERROR;
77using android::Vector;
Felipe Leme47e9be22016-12-21 15:37:07 -080078using android::os::dumpstate::CommandOptions;
79using android::os::dumpstate::DumpFileToFd;
Vishnu Naire97d6122018-01-18 13:58:56 -080080using android::os::dumpstate::DumpstateSectionReporter;
Felipe Leme47e9be22016-12-21 15:37:07 -080081using android::os::dumpstate::GetPidByName;
Vishnu Naire97d6122018-01-18 13:58:56 -080082using android::os::dumpstate::PropertiesHelper;
Felipe Leme47e9be22016-12-21 15:37:07 -080083
Colin Crossf45fa6b2012-03-26 12:38:26 -070084/* read before root is shed */
85static char cmdline_buf[16384] = "(unknown)";
86static const char *dump_traces_path = NULL;
87
Felipe Leme1d486fe2016-10-14 18:06:47 -070088// TODO: variables and functions below should be part of dumpstate object
89
Felipe Leme635ca312016-01-05 14:23:02 -080090static std::set<std::string> mount_points;
91void add_mountinfo();
Felipe Leme78f2c862015-12-21 09:55:22 -080092
Todd Poynor2a83daa2013-11-22 15:44:22 -080093#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
Mark Salyzyn7d0a7622016-06-24 14:06:15 -070094#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
Wei Wang509bb5d2017-06-09 14:42:12 -070095#define BLK_DEV_SYS_DIR "/sys/block"
Todd Poynor2a83daa2013-11-22 15:44:22 -080096
Wei Liu341938b2016-04-27 16:18:17 -070097#define RAFT_DIR "/data/misc/raft"
Felipe Lemee82a27d2016-01-05 13:35:44 -080098#define RECOVERY_DIR "/cache/recovery"
Mark Salyzynd6ab0112016-03-25 12:56:39 -070099#define RECOVERY_DATA_DIR "/data/misc/recovery"
Mark Salyzyn4d42dea2016-04-01 10:03:14 -0700100#define LOGPERSIST_DATA_DIR "/data/misc/logd"
David Brazdild2991962016-06-03 14:40:44 +0100101#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
102#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
Erik Kline08165202016-05-30 11:55:44 +0900103#define WLUTIL "/vendor/xbin/wlutil"
Vishnu Nair36b4cdb2017-11-17 10:27:05 -0800104#define WMTRACE_DATA_DIR "/data/misc/wmtrace"
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700105
Narayan Kamath8f788292017-05-25 13:20:39 +0100106// TODO(narayan): Since this information has to be kept in sync
107// with tombstoned, we should just put it in a common header.
108//
109// File: system/core/debuggerd/tombstoned/tombstoned.cpp
Narayan Kamathbd863722017-06-01 18:50:12 +0100110static const std::string TOMBSTONE_DIR = "/data/tombstones/";
111static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
112static const std::string ANR_DIR = "/data/anr/";
113static const std::string ANR_FILE_PREFIX = "anr_";
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700114
Narayan Kamath8f788292017-05-25 13:20:39 +0100115struct DumpData {
116 std::string name;
117 int fd;
118 time_t mtime;
119};
120
121static bool operator<(const DumpData& d1, const DumpData& d2) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100122 return d1.mtime > d2.mtime;
Narayan Kamath8f788292017-05-25 13:20:39 +0100123}
124
125static std::unique_ptr<std::vector<DumpData>> tombstone_data;
126static std::unique_ptr<std::vector<DumpData>> anr_data;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700127
Felipe Lemee844a9d2016-09-21 15:01:39 -0700128// TODO: temporary variables and functions used during C++ refactoring
129static Dumpstate& ds = Dumpstate::GetInstance();
Felipe Leme678727a2016-09-21 17:22:11 -0700130static int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand,
131 const CommandOptions& options = CommandOptions::DEFAULT) {
132 return ds.RunCommand(title, fullCommand, options);
133}
134static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
Felipe Lemebda15a02016-11-16 17:48:25 -0800135 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
Vishnu Nair6921f802017-11-22 09:17:23 -0800136 long dumpsysTimeoutMs = 0) {
137 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs);
Felipe Leme678727a2016-09-21 17:22:11 -0700138}
139static int DumpFile(const std::string& title, const std::string& path) {
140 return ds.DumpFile(title, path);
141}
Felipe Lemee82a27d2016-01-05 13:35:44 -0800142
Felipe Lemee844a9d2016-09-21 15:01:39 -0700143// Relative directory (inside the zip) for all files copied as-is into the bugreport.
144static const std::string ZIP_ROOT_DIR = "FS";
145
Steven Moreland7440ddb2016-12-15 16:13:39 -0800146// Must be hardcoded because dumpstate HAL implementation need SELinux access to it
Jie Song9fbfad02017-06-20 16:29:42 -0700147static const std::string kDumpstateBoardPath = "/bugreports/";
Vishnu Naire97d6122018-01-18 13:58:56 -0800148static const std::string kProtoPath = "proto/";
149static const std::string kProtoExt = ".proto";
Jie Song9fbfad02017-06-20 16:29:42 -0700150static const std::string kDumpstateBoardFiles[] = {
151 "dumpstate_board.txt",
Felipe Leme95d6ca52017-08-01 16:35:56 -0700152 "dumpstate_board.bin"
Jie Song9fbfad02017-06-20 16:29:42 -0700153};
154static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
155
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700156static constexpr char PROPERTY_EXTRA_OPTIONS[] = "dumpstate.options";
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700157static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Lemed071c682016-10-20 16:48:00 -0700158static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
Naveen Kallab53a1c92017-03-16 18:17:25 -0700159static constexpr char PROPERTY_EXTRA_TITLE[] = "dumpstate.options.title";
160static constexpr char PROPERTY_EXTRA_DESCRIPTION[] = "dumpstate.options.description";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700161
Felipe Lemef0292972016-11-22 13:57:05 -0800162static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
163
Narayan Kamath8f788292017-05-25 13:20:39 +0100164/*
Narayan Kamathbd863722017-06-01 18:50:12 +0100165 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
166 * The returned vector is sorted by the mtimes of the dumps. If |limit_by_mtime|
167 * is set, the vector only contains files that were written in the last 30 minutes.
Andreas Gamped0d76952017-08-22 13:08:37 -0700168 * If |limit_by_count| is set, the vector only contains the ten latest files.
Narayan Kamath8f788292017-05-25 13:20:39 +0100169 */
Narayan Kamathbd863722017-06-01 18:50:12 +0100170static std::vector<DumpData>* GetDumpFds(const std::string& dir_path,
171 const std::string& file_prefix,
Andreas Gamped0d76952017-08-22 13:08:37 -0700172 bool limit_by_mtime,
173 bool limit_by_count = true) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100174 const time_t thirty_minutes_ago = ds.now_ - 60 * 30;
175
Narayan Kamath8f788292017-05-25 13:20:39 +0100176 std::unique_ptr<std::vector<DumpData>> dump_data(new std::vector<DumpData>());
Narayan Kamathbd863722017-06-01 18:50:12 +0100177 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100178
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700179 if (dump_dir == nullptr) {
180 MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno));
181 return dump_data.release();
182 }
183
Narayan Kamathbd863722017-06-01 18:50:12 +0100184 struct dirent* entry = nullptr;
185 while ((entry = readdir(dump_dir.get()))) {
186 if (entry->d_type != DT_REG) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100187 continue;
188 }
189
Narayan Kamathbd863722017-06-01 18:50:12 +0100190 const std::string base_name(entry->d_name);
191 if (base_name.find(file_prefix) != 0) {
192 continue;
193 }
194
195 const std::string abs_path = dir_path + base_name;
196 android::base::unique_fd fd(
197 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
198 if (fd == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700199 MYLOGW("Unable to open dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamathbd863722017-06-01 18:50:12 +0100200 break;
201 }
202
203 struct stat st = {};
204 if (fstat(fd, &st) == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700205 MYLOGW("Unable to stat dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamath8f788292017-05-25 13:20:39 +0100206 continue;
207 }
208
Narayan Kamath3f31b632018-02-22 19:42:36 +0000209 if (limit_by_mtime && st.st_mtime < thirty_minutes_ago) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100210 MYLOGI("Excluding stale dump file: %s\n", abs_path.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100211 continue;
212 }
213
Narayan Kamathbd863722017-06-01 18:50:12 +0100214 DumpData data = {.name = abs_path, .fd = fd.release(), .mtime = st.st_mtime};
Narayan Kamath8f788292017-05-25 13:20:39 +0100215
216 dump_data->push_back(data);
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700217 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100218
219 std::sort(dump_data->begin(), dump_data->end());
220
Andreas Gamped0d76952017-08-22 13:08:37 -0700221 if (limit_by_count && dump_data->size() > 10) {
222 dump_data->erase(dump_data->begin() + 10, dump_data->end());
223 }
224
Narayan Kamath8f788292017-05-25 13:20:39 +0100225 return dump_data.release();
226}
227
Narayan Kamathbd863722017-06-01 18:50:12 +0100228static bool AddDumps(const std::vector<DumpData>::const_iterator start,
229 const std::vector<DumpData>::const_iterator end,
230 const char* type_name, const bool add_to_zip) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100231 bool dumped = false;
Narayan Kamathbd863722017-06-01 18:50:12 +0100232 for (auto it = start; it != end; ++it) {
233 const std::string& name = it->name;
234 const int fd = it->fd;
Narayan Kamath8f788292017-05-25 13:20:39 +0100235 dumped = true;
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100236
237 // Seek to the beginning of the file before dumping any data. A given
238 // DumpData entry might be dumped multiple times in the report.
239 //
240 // For example, the most recent ANR entry is dumped to the body of the
241 // main entry and it also shows up as a separate entry in the bugreport
242 // ZIP file.
243 if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) {
244 MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(),
245 strerror(errno));
246 }
247
Narayan Kamath8f788292017-05-25 13:20:39 +0100248 if (ds.IsZipping() && add_to_zip) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800249 if (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd, /* timeout = */ 0ms) != OK) {
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100250 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100251 }
252 } else {
253 dump_file_from_fd(type_name, name.c_str(), fd);
254 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100255 }
256
257 return dumped;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700258}
259
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100260static void CloseDumpFds(const std::vector<DumpData>* dumps) {
261 for (auto it = dumps->begin(); it != dumps->end(); ++it) {
262 close(it->fd);
263 }
264}
265
Felipe Leme635ca312016-01-05 14:23:02 -0800266// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700267void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800268 char path[PATH_MAX];
269
270 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
271 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700272 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800273 char linkname[PATH_MAX];
274 ssize_t r = readlink(path, linkname, PATH_MAX);
275 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800276 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800277 return;
278 }
279 linkname[r] = '\0';
280
281 if (mount_points.find(linkname) == mount_points.end()) {
282 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700283 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700284 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
Felipe Leme635ca312016-01-05 14:23:02 -0800285 mount_points.insert(linkname);
286 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800287 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800288 }
289 }
290}
291
292void add_mountinfo() {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700293 if (!ds.IsZipping()) return;
Felipe Leme678727a2016-09-21 17:22:11 -0700294 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800295 mount_points.clear();
Felipe Leme46b85da2016-11-21 17:40:45 -0800296 DurationReporter duration_reporter(title, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700297 for_each_pid(do_mountinfo, nullptr);
298 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800299}
300
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700301static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
302{
303 DIR *d;
304 struct dirent *de;
305 char path[PATH_MAX];
306
307 d = opendir(driverpath);
308 if (d == NULL) {
309 return;
310 }
311
312 while ((de = readdir(d))) {
313 if (de->d_type != DT_LNK) {
314 continue;
315 }
316 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700317 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700318 }
319
320 closedir(d);
321}
322
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700323
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700324
325// dump anrd's trace and add to the zip file.
326// 1. check if anrd is running on this device.
327// 2. send a SIGUSR1 to its pid which will dump anrd's trace.
328// 3. wait until the trace generation completes and add to the zip file.
329static bool dump_anrd_trace() {
330 unsigned int pid;
331 char buf[50], path[PATH_MAX];
332 struct dirent *trace;
333 struct stat st;
334 DIR *trace_dir;
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700335 int retry = 5;
336 long max_ctime = 0, old_mtime;
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700337 long long cur_size = 0;
338 const char *trace_path = "/data/misc/anrd/";
339
Felipe Leme1d486fe2016-10-14 18:06:47 -0700340 if (!ds.IsZipping()) {
341 MYLOGE("Not dumping anrd trace because it's not a zipped bugreport\n");
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700342 return false;
343 }
344
345 // find anrd's pid if it is running.
Ecco Park61ffcf72016-10-27 15:46:26 -0700346 pid = GetPidByName("/system/xbin/anrd");
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700347
348 if (pid > 0) {
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700349 if (stat(trace_path, &st) == 0) {
350 old_mtime = st.st_mtime;
351 } else {
352 MYLOGE("Failed to find: %s\n", trace_path);
353 return false;
354 }
355
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700356 // send SIGUSR1 to the anrd to generate a trace.
357 sprintf(buf, "%u", pid);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700358 if (RunCommand("ANRD_DUMP", {"kill", "-SIGUSR1", buf},
Felipe Leme30dbfa12016-09-02 12:43:26 -0700359 CommandOptions::WithTimeout(1).Build())) {
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700360 MYLOGE("anrd signal timed out. Please manually collect trace\n");
361 return false;
362 }
363
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700364 while (retry-- > 0 && old_mtime == st.st_mtime) {
365 sleep(1);
366 stat(trace_path, &st);
367 }
368
369 if (retry < 0 && old_mtime == st.st_mtime) {
370 MYLOGE("Failed to stat %s or trace creation timeout\n", trace_path);
371 return false;
372 }
373
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700374 // identify the trace file by its creation time.
375 if (!(trace_dir = opendir(trace_path))) {
376 MYLOGE("Can't open trace file under %s\n", trace_path);
377 }
378 while ((trace = readdir(trace_dir))) {
379 if (strcmp(trace->d_name, ".") == 0
380 || strcmp(trace->d_name, "..") == 0) {
381 continue;
382 }
383 sprintf(path, "%s%s", trace_path, trace->d_name);
384 if (stat(path, &st) == 0) {
385 if (st.st_ctime > max_ctime) {
386 max_ctime = st.st_ctime;
387 sprintf(buf, "%s", trace->d_name);
388 }
389 }
390 }
391 closedir(trace_dir);
392
393 // Wait until the dump completes by checking the size of the trace.
394 if (max_ctime > 0) {
395 sprintf(path, "%s%s", trace_path, buf);
396 while(true) {
397 sleep(1);
398 if (stat(path, &st) == 0) {
399 if (st.st_size == cur_size) {
400 break;
401 } else if (st.st_size > cur_size) {
402 cur_size = st.st_size;
403 } else {
404 return false;
405 }
406 } else {
407 MYLOGE("Cant stat() %s anymore\n", path);
408 return false;
409 }
410 }
411 // Add to the zip file.
Felipe Leme1d486fe2016-10-14 18:06:47 -0700412 if (!ds.AddZipEntry("anrd_trace.txt", path)) {
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700413 MYLOGE("Unable to add anrd_trace file %s to zip file\n", path);
414 } else {
415 if (remove(path)) {
416 MYLOGE("Error removing anrd_trace file %s: %s", path, strerror(errno));
417 }
418 return true;
419 }
420 } else {
421 MYLOGE("Can't stats any trace file under %s\n", trace_path);
422 }
423 }
424 return false;
425}
426
Felipe Lemeefd7e272016-05-18 09:27:16 -0700427static void dump_systrace() {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700428 if (!ds.IsZipping()) {
429 MYLOGD("Not dumping systrace because it's not a zipped bugreport\n");
Felipe Leme71a74ac2016-03-17 15:43:25 -0700430 return;
431 }
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700432 std::string systrace_path = ds.GetPath("-systrace.txt");
Felipe Leme14e034a2016-03-30 18:51:03 -0700433 if (systrace_path.empty()) {
434 MYLOGE("Not dumping systrace because path is empty\n");
435 return;
436 }
Felipe Leme71a74ac2016-03-17 15:43:25 -0700437 const char* path = "/sys/kernel/debug/tracing/tracing_on";
438 long int is_tracing;
439 if (read_file_as_long(path, &is_tracing)) {
440 return; // error already logged
441 }
442 if (is_tracing <= 0) {
443 MYLOGD("Skipping systrace because '%s' content is '%ld'\n", path, is_tracing);
444 return;
445 }
446
Felipe Leme14e034a2016-03-30 18:51:03 -0700447 MYLOGD("Running '/system/bin/atrace --async_dump -o %s', which can take several minutes",
448 systrace_path.c_str());
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700449 if (RunCommand("SYSTRACE", {"/system/bin/atrace", "--async_dump", "-o", systrace_path},
Felipe Leme30dbfa12016-09-02 12:43:26 -0700450 CommandOptions::WithTimeout(120).Build())) {
Felipe Leme14e034a2016-03-30 18:51:03 -0700451 MYLOGE("systrace timed out, its zip entry will be incomplete\n");
Felipe Lemec7fe8fe2016-09-21 18:13:20 -0700452 // TODO: RunCommand tries to kill the process, but atrace doesn't die
Felipe Leme30dbfa12016-09-02 12:43:26 -0700453 // peacefully; ideally, we should call strace to stop itself, but there is no such option
454 // yet (just a --async_stop, which stops and dump
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700455 // if (RunCommand("SYSTRACE", {"/system/bin/atrace", "--kill"})) {
Felipe Leme30dbfa12016-09-02 12:43:26 -0700456 // MYLOGE("could not stop systrace ");
457 // }
Felipe Leme14e034a2016-03-30 18:51:03 -0700458 }
Felipe Leme1d486fe2016-10-14 18:06:47 -0700459 if (!ds.AddZipEntry("systrace.txt", systrace_path)) {
Felipe Leme14e034a2016-03-30 18:51:03 -0700460 MYLOGE("Unable to add systrace file %s to zip file\n", systrace_path.c_str());
Felipe Leme71a74ac2016-03-17 15:43:25 -0700461 } else {
Felipe Leme14e034a2016-03-30 18:51:03 -0700462 if (remove(systrace_path.c_str())) {
463 MYLOGE("Error removing systrace file %s: %s", systrace_path.c_str(), strerror(errno));
464 }
Felipe Leme71a74ac2016-03-17 15:43:25 -0700465 }
466}
467
Felipe Lemeefd7e272016-05-18 09:27:16 -0700468static void dump_raft() {
Felipe Lemef0292972016-11-22 13:57:05 -0800469 if (PropertiesHelper::IsUserBuild()) {
Wei Liu341938b2016-04-27 16:18:17 -0700470 return;
471 }
472
Felipe Leme1d486fe2016-10-14 18:06:47 -0700473 std::string raft_path = ds.GetPath("-raft_log.txt");
474 if (raft_path.empty()) {
475 MYLOGD("raft_path is empty\n");
Wei Liu341938b2016-04-27 16:18:17 -0700476 return;
477 }
Wei Liuf0e78d42016-05-25 14:21:02 -0700478
479 struct stat s;
480 if (stat(RAFT_DIR, &s) != 0 || !S_ISDIR(s.st_mode)) {
481 MYLOGD("%s does not exist or is not a directory\n", RAFT_DIR);
482 return;
483 }
484
Felipe Leme30dbfa12016-09-02 12:43:26 -0700485 CommandOptions options = CommandOptions::WithTimeout(600).Build();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700486 if (!ds.IsZipping()) {
487 // Write compressed and encoded raft logs to stdout if it's not a zipped bugreport.
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700488 RunCommand("RAFT LOGS", {"logcompressor", "-r", RAFT_DIR}, options);
Wei Liu341938b2016-04-27 16:18:17 -0700489 return;
490 }
491
Felipe Leme1d486fe2016-10-14 18:06:47 -0700492 RunCommand("RAFT LOGS", {"logcompressor", "-n", "-r", RAFT_DIR, "-o", raft_path}, options);
493 if (!ds.AddZipEntry("raft_log.txt", raft_path)) {
494 MYLOGE("Unable to add raft log %s to zip file\n", raft_path.c_str());
Wei Liu341938b2016-04-27 16:18:17 -0700495 } else {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700496 if (remove(raft_path.c_str())) {
497 MYLOGE("Error removing raft file %s: %s\n", raft_path.c_str(), strerror(errno));
Wei Liu341938b2016-04-27 16:18:17 -0700498 }
499 }
500}
501
Mark Salyzyn326842f2015-04-30 09:49:41 -0700502static bool skip_not_stat(const char *path) {
503 static const char stat[] = "/stat";
504 size_t len = strlen(path);
505 if (path[len - 1] == '/') { /* Directory? */
506 return false;
507 }
508 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
509}
510
Felipe Leme4c2d6632016-09-28 14:32:00 -0700511static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800512 return false;
513}
514
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700515unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700516
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800517//
518// stat offsets
519// Name units description
520// ---- ----- -----------
521// read I/Os requests number of read I/Os processed
522#define __STAT_READ_IOS 0
523// read merges requests number of read I/Os merged with in-queue I/O
524#define __STAT_READ_MERGES 1
525// read sectors sectors number of sectors read
526#define __STAT_READ_SECTORS 2
527// read ticks milliseconds total wait time for read requests
528#define __STAT_READ_TICKS 3
529// write I/Os requests number of write I/Os processed
530#define __STAT_WRITE_IOS 4
531// write merges requests number of write I/Os merged with in-queue I/O
532#define __STAT_WRITE_MERGES 5
533// write sectors sectors number of sectors written
534#define __STAT_WRITE_SECTORS 6
535// write ticks milliseconds total wait time for write requests
536#define __STAT_WRITE_TICKS 7
537// in_flight requests number of I/Os currently in flight
538#define __STAT_IN_FLIGHT 8
539// io_ticks milliseconds total time this block device has been active
540#define __STAT_IO_TICKS 9
541// time_in_queue milliseconds total wait time for all requests
542#define __STAT_IN_QUEUE 10
543#define __STAT_NUMBER_FIELD 11
544//
545// read I/Os, write I/Os
546// =====================
547//
548// These values increment when an I/O request completes.
549//
550// read merges, write merges
551// =========================
552//
553// These values increment when an I/O request is merged with an
554// already-queued I/O request.
555//
556// read sectors, write sectors
557// ===========================
558//
559// These values count the number of sectors read from or written to this
560// block device. The "sectors" in question are the standard UNIX 512-byte
561// sectors, not any device- or filesystem-specific block size. The
562// counters are incremented when the I/O completes.
563#define SECTOR_SIZE 512
564//
565// read ticks, write ticks
566// =======================
567//
568// These values count the number of milliseconds that I/O requests have
569// waited on this block device. If there are multiple I/O requests waiting,
570// these values will increase at a rate greater than 1000/second; for
571// example, if 60 read requests wait for an average of 30 ms, the read_ticks
572// field will increase by 60*30 = 1800.
573//
574// in_flight
575// =========
576//
577// This value counts the number of I/O requests that have been issued to
578// the device driver but have not yet completed. It does not include I/O
579// requests that are in the queue but not yet issued to the device driver.
580//
581// io_ticks
582// ========
583//
584// This value counts the number of milliseconds during which the device has
585// had I/O requests queued.
586//
587// time_in_queue
588// =============
589//
590// This value counts the number of milliseconds that I/O requests have waited
591// on this block device. If there are multiple I/O requests waiting, this
592// value will increase as the product of the number of milliseconds times the
593// number of requests waiting (see "read ticks" above for an example).
594#define S_TO_MS 1000
595//
596
Mark Salyzyn326842f2015-04-30 09:49:41 -0700597static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800598 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700599 bool z;
600 char *cp, *buffer = NULL;
601 size_t i = 0;
602 FILE *fp = fdopen(fd, "rb");
603 getline(&buffer, &i, fp);
604 fclose(fp);
605 if (!buffer) {
606 return -errno;
607 }
608 i = strlen(buffer);
609 while ((i > 0) && (buffer[i - 1] == '\n')) {
610 buffer[--i] = '\0';
611 }
612 if (!*buffer) {
613 free(buffer);
614 return 0;
615 }
616 z = true;
617 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800618 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700619 if (fields[i] != 0) {
620 z = false;
621 }
622 }
623 if (z) { /* never accessed */
624 free(buffer);
625 return 0;
626 }
627
Wei Wang509bb5d2017-06-09 14:42:12 -0700628 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
629 path += sizeof(BLK_DEV_SYS_DIR) - 1;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700630 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700631
632 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
633 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
634 "W-wait", "in-fli", "activ", "T-wait", path, buffer);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700635 free(buffer);
636
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800637 if (fields[__STAT_IO_TICKS]) {
638 unsigned long read_perf = 0;
639 unsigned long read_ios = 0;
640 if (fields[__STAT_READ_TICKS]) {
641 unsigned long long divisor = fields[__STAT_READ_TICKS]
642 * fields[__STAT_IO_TICKS];
643 read_perf = ((unsigned long long)SECTOR_SIZE
644 * fields[__STAT_READ_SECTORS]
645 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
646 / divisor;
647 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
648 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
649 / divisor;
650 }
651
652 unsigned long write_perf = 0;
653 unsigned long write_ios = 0;
654 if (fields[__STAT_WRITE_TICKS]) {
655 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
656 * fields[__STAT_IO_TICKS];
657 write_perf = ((unsigned long long)SECTOR_SIZE
658 * fields[__STAT_WRITE_SECTORS]
659 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
660 / divisor;
661 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
662 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
663 / divisor;
664 }
665
666 unsigned queue = (fields[__STAT_IN_QUEUE]
667 + (fields[__STAT_IO_TICKS] >> 1))
668 / fields[__STAT_IO_TICKS];
669
670 if (!write_perf && !write_ios) {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700671 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 -0800672 } else {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700673 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 -0800674 read_ios, write_perf, write_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800675 }
676
677 /* bugreport timeout factor adjustment */
678 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
679 worst_write_perf = write_perf;
680 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700681 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700682 return 0;
683}
684
Yao Chenbe3bbc12018-01-17 16:31:10 -0800685static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
686
687/* timeout in ms to read a list of buffers */
688static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
689 unsigned long timeout_ms = 0;
690 for (const auto& buffer : buffers) {
691 log_id_t id = android_name_to_log_id(buffer.c_str());
692 unsigned long property_size = __android_logger_get_buffer_size(id);
693 /* Engineering margin is ten-fold our guess */
694 timeout_ms += 10 * (property_size + worst_write_perf) / worst_write_perf;
695 }
696 return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700697}
698
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700699void Dumpstate::PrintHeader() const {
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700700 std::string build, fingerprint, radio, bootloader, network;
701 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700702
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700703 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
704 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700705 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
706 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
707 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700708 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
Colin Crossf45fa6b2012-03-26 12:38:26 -0700709
Felipe Lemed8b94e52016-12-08 10:21:44 -0800710 printf("========================================================\n");
711 printf("== dumpstate: %s\n", date);
712 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700713
Felipe Lemed8b94e52016-12-08 10:21:44 -0800714 printf("\n");
715 printf("Build: %s\n", build.c_str());
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700716 // NOTE: fingerprint entry format is important for other tools.
Felipe Lemed8b94e52016-12-08 10:21:44 -0800717 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
718 printf("Bootloader: %s\n", bootloader.c_str());
719 printf("Radio: %s\n", radio.c_str());
720 printf("Network: %s\n", network.c_str());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700721
Felipe Lemed8b94e52016-12-08 10:21:44 -0800722 printf("Kernel: ");
Felipe Lemef0292972016-11-22 13:57:05 -0800723 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
Felipe Lemed8b94e52016-12-08 10:21:44 -0800724 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
Felipe Leme7709f8a2017-12-05 09:30:09 -0800725 printf("Uptime: ");
726 RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"},
727 CommandOptions::WithTimeout(1).Always().Build());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800728 printf("Bugreport format version: %s\n", version_.c_str());
729 printf("Dumpstate info: id=%d pid=%d dry_run=%d args=%s extra_options=%s\n", id_, pid_,
730 PropertiesHelper::IsDryRun(), args_.c_str(), extra_options_.c_str());
731 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800732}
733
Felipe Leme24b66ee2016-06-16 10:55:26 -0700734// List of file extensions that can cause a zip file attachment to be rejected by some email
735// service providers.
736static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
737 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
738 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
739 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
740};
741
Vishnu Naire97d6122018-01-18 13:58:56 -0800742status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd,
743 std::chrono::milliseconds timeout = 0ms) {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700744 if (!IsZipping()) {
745 MYLOGD("Not adding zip entry %s from fd because it's not a zipped bugreport\n",
746 entry_name.c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -0800747 return INVALID_OPERATION;
Felipe Leme111b9d02016-02-03 09:28:24 -0800748 }
Felipe Leme24b66ee2016-06-16 10:55:26 -0700749 std::string valid_name = entry_name;
750
751 // Rename extension if necessary.
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -0700752 size_t idx = entry_name.rfind('.');
Felipe Leme24b66ee2016-06-16 10:55:26 -0700753 if (idx != std::string::npos) {
754 std::string extension = entry_name.substr(idx);
755 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
756 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
757 valid_name = entry_name + ".renamed";
758 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
759 }
760 }
761
Felipe Leme6fe9db62016-02-12 09:04:16 -0800762 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
763 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700764 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), ZipWriter::kCompress,
765 get_mtime(fd, ds.now_));
Felipe Leme1d486fe2016-10-14 18:06:47 -0700766 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700767 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700768 ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800769 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800770 }
Vishnu Naire97d6122018-01-18 13:58:56 -0800771 auto start = std::chrono::steady_clock::now();
772 auto end = start + timeout;
773 struct pollfd pfd = {fd, POLLIN};
Felipe Lemee82a27d2016-01-05 13:35:44 -0800774
Felipe Leme770410d2016-01-26 17:07:14 -0800775 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800776 while (1) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800777 if (timeout.count() > 0) {
778 // lambda to recalculate the timeout.
779 auto time_left_ms = [end]() {
780 auto now = std::chrono::steady_clock::now();
781 auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
782 return std::max(diff.count(), 0LL);
783 };
784
785 int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
786 if (rc < 0) {
787 MYLOGE("Error in poll while adding from fd to zip entry %s:%s", entry_name.c_str(),
788 strerror(errno));
789 return -errno;
790 } else if (rc == 0) {
791 MYLOGE("Timed out adding from fd to zip entry %s:%s Timeout:%lldms",
792 entry_name.c_str(), strerror(errno), timeout.count());
793 return TIMED_OUT;
794 }
795 }
796
Zach Riggle22200402016-08-18 01:01:24 -0400797 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800798 if (bytes_read == 0) {
799 break;
800 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800801 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800802 return -errno;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800803 }
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700804 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800805 if (err) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700806 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800807 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800808 }
809 }
810
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700811 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700812 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700813 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800814 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800815 }
816
Vishnu Naire97d6122018-01-18 13:58:56 -0800817 return OK;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800818}
819
Felipe Leme1d486fe2016-10-14 18:06:47 -0700820bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
821 android::base::unique_fd fd(
822 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700823 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800824 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800825 return false;
826 }
827
Vishnu Naire97d6122018-01-18 13:58:56 -0800828 return (AddZipEntryFromFd(entry_name, fd.get()) == OK);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800829}
830
831/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700832static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800833 return (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) == OK) ? 0 : 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800834}
835
Felipe Leme1d486fe2016-10-14 18:06:47 -0700836void Dumpstate::AddDir(const std::string& dir, bool recursive) {
837 if (!IsZipping()) {
838 MYLOGD("Not adding dir %s because it's not a zipped bugreport\n", dir.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800839 return;
840 }
Felipe Leme678727a2016-09-21 17:22:11 -0700841 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
Felipe Leme46b85da2016-11-21 17:40:45 -0800842 DurationReporter duration_reporter(dir, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700843 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800844}
845
Felipe Leme1d486fe2016-10-14 18:06:47 -0700846bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
847 if (!IsZipping()) {
848 MYLOGD("Not adding text zip entry %s because it's not a zipped bugreport\n",
849 entry_name.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800850 return false;
851 }
Felipe Lemecbce55d2016-02-08 09:53:18 -0800852 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700853 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, ds.now_);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700854 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700855 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700856 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800857 return false;
858 }
859
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700860 err = zip_writer_->WriteBytes(content.c_str(), content.length());
Felipe Leme1d486fe2016-10-14 18:06:47 -0700861 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700862 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700863 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800864 return false;
865 }
866
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700867 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700868 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700869 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800870 return false;
871 }
872
873 return true;
874}
875
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800876static void DoKmsg() {
877 struct stat st;
878 if (!stat(PSTORE_LAST_KMSG, &st)) {
879 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
880 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
881 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
882 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
883 } else {
884 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
885 DumpFile("LAST KMSG", "/proc/last_kmsg");
886 }
887}
888
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800889static void DoKernelLogcat() {
Yao Chenbe3bbc12018-01-17 16:31:10 -0800890 unsigned long timeout_ms = logcat_timeout({"kernel"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800891 RunCommand(
892 "KERNEL LOG",
893 {"logcat", "-b", "kernel", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
894 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
895}
896
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800897static void DoLogcat() {
Vishnu Nair6921f802017-11-22 09:17:23 -0800898 unsigned long timeout_ms;
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800899 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
900 // calculate timeout
Yao Chenbe3bbc12018-01-17 16:31:10 -0800901 timeout_ms = logcat_timeout({"main", "system", "crash"});
Tony Makae737652017-03-30 17:47:09 +0100902 RunCommand("SYSTEM LOG",
Vishnu Nair6921f802017-11-22 09:17:23 -0800903 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
904 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -0800905 timeout_ms = logcat_timeout({"events"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800906 RunCommand(
907 "EVENT LOG",
908 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
909 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -0800910 timeout_ms = logcat_timeout({"stats"});
911 RunCommand(
912 "STATS LOG",
913 {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
914 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
915 timeout_ms = logcat_timeout({"radio"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800916 RunCommand(
917 "RADIO LOG",
918 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
919 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800920
921 RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
922
923 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800924 RunCommand("LAST LOGCAT", {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable",
925 "-v", "uid", "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800926}
927
Jayachandran Ca94c7172017-06-10 15:08:12 -0700928static void DumpIpTablesAsRoot() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700929 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
930 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +0900931 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -0700932 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +0900933 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
934 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
935 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
936 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -0700937}
938
Narayan Kamath8f788292017-05-25 13:20:39 +0100939static void AddGlobalAnrTraceFile(const bool add_to_zip, const std::string& anr_traces_file,
940 const std::string& anr_traces_dir) {
Felipe Lemee184f662016-10-27 10:04:47 -0700941 std::string dump_traces_dir;
942
Felipe Lemee184f662016-10-27 10:04:47 -0700943 if (dump_traces_path != nullptr) {
944 if (add_to_zip) {
945 dump_traces_dir = dirname(dump_traces_path);
946 MYLOGD("Adding ANR traces (directory %s) to the zip file\n", dump_traces_dir.c_str());
947 ds.AddDir(dump_traces_dir, true);
948 } else {
949 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
950 dump_traces_path);
951 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
952 }
953 }
954
Felipe Lemee184f662016-10-27 10:04:47 -0700955
956 // Make sure directory is not added twice.
957 // TODO: this is an overzealous check because it's relying on dump_traces_path - which is
958 // generated by dump_traces() - and anr_traces_path - which is retrieved from a system
959 // property - but in reality they're the same path (although the former could be nullptr).
960 // Anyways, once dump_traces() is refactored as a private Dumpstate function, this logic should
961 // be revisited.
962 bool already_dumped = anr_traces_dir == dump_traces_dir;
963
Narayan Kamath8f788292017-05-25 13:20:39 +0100964 MYLOGD("AddGlobalAnrTraceFile(): dump_traces_dir=%s, anr_traces_dir=%s, already_dumped=%d\n",
Felipe Lemee184f662016-10-27 10:04:47 -0700965 dump_traces_dir.c_str(), anr_traces_dir.c_str(), already_dumped);
966
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100967 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
968 open(anr_traces_file.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
969 if (fd.get() < 0) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100970 printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_file.c_str(), strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -0700971 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +0100972 if (add_to_zip) {
973 if (!already_dumped) {
974 MYLOGD("Adding dalvik ANR traces (directory %s) to the zip file\n",
975 anr_traces_dir.c_str());
976 ds.AddDir(anr_traces_dir, true);
Felipe Lemee184f662016-10-27 10:04:47 -0700977 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100978 } else {
979 MYLOGD("Dumping last ANR traces (%s) to the main bugreport entry\n",
980 anr_traces_file.c_str());
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100981 dump_file_from_fd("VM TRACES AT LAST ANR", anr_traces_file.c_str(), fd.get());
Narayan Kamath8f788292017-05-25 13:20:39 +0100982 }
983 }
984}
985
986static void AddAnrTraceDir(const bool add_to_zip, const std::string& anr_traces_dir) {
987 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
988 anr_traces_dir.c_str());
989
990 // If we're here, dump_traces_path will always be a temporary file
991 // (created with mkostemp or similar) that contains dumps taken earlier
992 // on in the process.
993 if (dump_traces_path != nullptr) {
994 if (add_to_zip) {
995 ds.AddZipEntry(ZIP_ROOT_DIR + anr_traces_dir + "/traces-just-now.txt", dump_traces_path);
996 } else {
997 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
998 dump_traces_path);
999 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
1000 }
1001
1002 const int ret = unlink(dump_traces_path);
1003 if (ret == -1) {
1004 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
1005 strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -07001006 }
1007 }
1008
Narayan Kamathbd863722017-06-01 18:50:12 +01001009 // Add a specific message for the first ANR Dump.
1010 if (anr_data->size() > 0) {
1011 AddDumps(anr_data->begin(), anr_data->begin() + 1,
1012 "VM TRACES AT LAST ANR", add_to_zip);
1013
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001014 // The "last" ANR will always be included as separate entry in the zip file. In addition,
1015 // it will be present in the body of the main entry if |add_to_zip| == false.
1016 //
1017 // Historical ANRs are always included as separate entries in the bugreport zip file.
1018 AddDumps(anr_data->begin() + ((add_to_zip) ? 1 : 0), anr_data->end(),
1019 "HISTORICAL ANR", true /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001020 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +01001021 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
1022 }
1023}
1024
1025static void AddAnrTraceFiles() {
1026 const bool add_to_zip = ds.IsZipping() && ds.version_ == VERSION_SPLIT_ANR;
1027
1028 std::string anr_traces_file;
1029 std::string anr_traces_dir;
1030 bool is_global_trace_file = true;
1031
1032 // First check whether the stack-trace-dir property is set. When it's set,
1033 // each ANR trace will be written to a separate file and not to a global
1034 // stack trace file.
1035 anr_traces_dir = android::base::GetProperty("dalvik.vm.stack-trace-dir", "");
1036 if (anr_traces_dir.empty()) {
1037 anr_traces_file = android::base::GetProperty("dalvik.vm.stack-trace-file", "");
1038 if (!anr_traces_file.empty()) {
Narayan Kamath8f788292017-05-25 13:20:39 +01001039 anr_traces_dir = dirname(anr_traces_file.c_str());
1040 }
Narayan Kamathbd863722017-06-01 18:50:12 +01001041 } else {
1042 is_global_trace_file = false;
Narayan Kamath8f788292017-05-25 13:20:39 +01001043 }
1044
1045 // We have neither configured a global trace file nor a trace directory,
1046 // there will be nothing to dump.
1047 if (anr_traces_file.empty() && anr_traces_dir.empty()) {
1048 printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
Felipe Lemee184f662016-10-27 10:04:47 -07001049 return;
1050 }
1051
Narayan Kamath8f788292017-05-25 13:20:39 +01001052 if (is_global_trace_file) {
1053 AddGlobalAnrTraceFile(add_to_zip, anr_traces_file, anr_traces_dir);
1054 } else {
1055 AddAnrTraceDir(add_to_zip, anr_traces_dir);
1056 }
1057
Felipe Lemee184f662016-10-27 10:04:47 -07001058 /* slow traces for slow operations */
1059 struct stat st;
Narayan Kamath8f788292017-05-25 13:20:39 +01001060 if (!anr_traces_dir.empty()) {
Felipe Lemee184f662016-10-27 10:04:47 -07001061 int i = 0;
Narayan Kamath8f788292017-05-25 13:20:39 +01001062 while (true) {
1063 const std::string slow_trace_path =
1064 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
1065 if (stat(slow_trace_path.c_str(), &st)) {
Felipe Lemee184f662016-10-27 10:04:47 -07001066 // No traces file at this index, done with the files.
1067 break;
1068 }
Narayan Kamath8f788292017-05-25 13:20:39 +01001069 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
Felipe Lemee184f662016-10-27 10:04:47 -07001070 i++;
1071 }
1072 }
1073}
1074
Wei Wang509bb5d2017-06-09 14:42:12 -07001075static void DumpBlockStatFiles() {
1076 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -07001077
Wei Wang1dc1ef52017-06-12 11:28:37 -07001078 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
1079
1080 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001081 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1082 return;
1083 }
1084
1085 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -07001086 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001087 if ((d->d_name[0] == '.')
1088 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1089 || (d->d_name[1] == '\0'))) {
1090 continue;
1091 }
1092 const std::string new_path =
1093 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1094 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1095 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1096 printf("\n");
1097 }
Wei Wang1dc1ef52017-06-12 11:28:37 -07001098 return;
Wei Wang509bb5d2017-06-09 14:42:12 -07001099}
Jayachandran Ca94c7172017-06-10 15:08:12 -07001100
1101static void DumpPacketStats() {
1102 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
1103 DumpFile("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
1104 DumpFile("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
1105 DumpFile("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
1106 DumpFile("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
1107}
1108
1109static void DumpIpAddrAndRules() {
1110 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
1111 RunCommand("NETWORK INTERFACES", {"ip", "link"});
1112 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1113 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1114 RunCommand("IP RULES", {"ip", "rule", "show"});
1115 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1116}
1117
Vishnu Nair64afc022018-02-01 15:29:34 -08001118static void RunDumpsysTextByPriority(const std::string& title, int priority,
1119 std::chrono::milliseconds timeout,
1120 std::chrono::milliseconds service_timeout) {
1121 auto start = std::chrono::steady_clock::now();
Vishnu Naire97d6122018-01-18 13:58:56 -08001122 sp<android::IServiceManager> sm = defaultServiceManager();
1123 Dumpsys dumpsys(sm.get());
Vishnu Naire97d6122018-01-18 13:58:56 -08001124 Vector<String16> args;
1125 Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
Vishnu Naire97d6122018-01-18 13:58:56 -08001126 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1127 for (const String16& service : services) {
1128 std::string path(title);
1129 path.append(" - ").append(String8(service).c_str());
1130 DumpstateSectionReporter section_reporter(path, ds.listener_, ds.report_section_);
1131 size_t bytes_written = 0;
1132 status_t status = dumpsys.startDumpThread(service, args);
1133 if (status == OK) {
1134 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1135 std::chrono::duration<double> elapsed_seconds;
1136 status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
1137 /* as_proto = */ false, elapsed_seconds, bytes_written);
1138 section_reporter.setSize(bytes_written);
1139 dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
1140 bool dump_complete = (status == OK);
1141 dumpsys.stopDumpThread(dump_complete);
1142 }
1143 section_reporter.setStatus(status);
1144
1145 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1146 std::chrono::steady_clock::now() - start);
1147 if (elapsed_duration > timeout) {
1148 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1149 elapsed_duration.count());
1150 break;
1151 }
1152 }
1153}
1154
Vishnu Nair64afc022018-02-01 15:29:34 -08001155static void RunDumpsysText(const std::string& title, int priority,
1156 std::chrono::milliseconds timeout,
1157 std::chrono::milliseconds service_timeout) {
1158 DurationReporter duration_reporter(title);
1159 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1160 fsync(STDOUT_FILENO);
1161 RunDumpsysTextByPriority(title, priority, timeout, service_timeout);
1162}
1163
1164/* Dump all services registered with Normal or Default priority. */
1165static void RunDumpsysTextNormalPriority(const std::string& title,
1166 std::chrono::milliseconds timeout,
1167 std::chrono::milliseconds service_timeout) {
1168 DurationReporter duration_reporter(title);
1169 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1170 fsync(STDOUT_FILENO);
1171 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout,
1172 service_timeout);
1173 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1174 service_timeout);
1175}
1176
1177static void RunDumpsysProto(const std::string& title, int priority,
1178 std::chrono::milliseconds timeout,
1179 std::chrono::milliseconds service_timeout) {
Vishnu Naire97d6122018-01-18 13:58:56 -08001180 sp<android::IServiceManager> sm = defaultServiceManager();
1181 Dumpsys dumpsys(sm.get());
1182 Vector<String16> args;
1183 Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
1184 DurationReporter duration_reporter(title);
1185
1186 auto start = std::chrono::steady_clock::now();
1187 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
1188 for (const String16& service : services) {
1189 std::string path(kProtoPath);
1190 path.append(String8(service).c_str());
1191 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
1192 path.append("_CRITICAL");
1193 } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
1194 path.append("_HIGH");
1195 }
1196 path.append(kProtoExt);
1197 DumpstateSectionReporter section_reporter(path, ds.listener_, ds.report_section_);
1198 status_t status = dumpsys.startDumpThread(service, args);
1199 if (status == OK) {
1200 status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
1201 bool dumpTerminated = (status == OK);
1202 dumpsys.stopDumpThread(dumpTerminated);
1203 }
1204 ZipWriter::FileEntry file_entry;
1205 ds.zip_writer_->GetLastEntry(&file_entry);
1206 section_reporter.setSize(file_entry.compressed_size);
1207 section_reporter.setStatus(status);
1208
1209 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1210 std::chrono::steady_clock::now() - start);
1211 if (elapsed_duration > timeout) {
1212 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1213 elapsed_duration.count());
1214 break;
1215 }
1216 }
1217}
1218
Vishnu Nair780b1282017-10-10 13:57:24 -07001219// Runs dumpsys on services that must dump first and and will take less than 100ms to dump.
1220static void RunDumpsysCritical() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001221 RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1222 /* timeout= */ 5s, /* service_timeout= */ 500ms);
1223 RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1224 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Vishnu Nair780b1282017-10-10 13:57:24 -07001225}
1226
1227// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
1228static void RunDumpsysHigh() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001229 // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
1230 // high priority. Reduce timeout once they are able to dump in a shorter time or
1231 // moved to a parallel task.
1232 RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1233 /* timeout= */ 90s, /* service_timeout= */ 30s);
1234 RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1235 /* timeout= */ 5s, /* service_timeout= */ 1s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001236}
1237
1238// Runs dumpsys on services that must dump but can take up to 10s to dump.
1239static void RunDumpsysNormal() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001240 RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
1241 RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1242 /* timeout= */ 90s, /* service_timeout= */ 10s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001243}
1244
Steven Moreland44cd9482018-01-04 16:24:13 -08001245static void DumpHals() {
1246 using android::sp;
1247 using android::hidl::manager::V1_0::IServiceManager;
1248 using android::hardware::defaultServiceManager;
1249
1250 sp<IServiceManager> sm = defaultServiceManager();
1251 if (sm == nullptr) {
1252 MYLOGE("Could not retrieve hwservicemanager to dump hals.\n");
1253 return;
1254 }
1255
1256 auto ret = sm->list([&](const auto& interfaces) {
1257 for (const std::string& interface : interfaces) {
1258 std::string cleanName = interface;
1259 std::replace_if(cleanName.begin(),
1260 cleanName.end(),
1261 [](char c) {
1262 return !isalnum(c) &&
1263 std::string("@-_:.").find(c) == std::string::npos;
1264 }, '_');
1265 const std::string path = kDumpstateBoardPath + "lshal_debug_" + cleanName;
1266
1267 {
1268 auto fd = android::base::unique_fd(
1269 TEMP_FAILURE_RETRY(open(path.c_str(),
1270 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1271 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1272 if (fd < 0) {
1273 MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str());
1274 continue;
1275 }
1276 RunCommandToFd(fd,
1277 "",
Steven Morelandc81cd3c2018-01-18 14:36:26 -08001278 {"lshal", "debug", "-E", interface},
Steven Moreland44cd9482018-01-04 16:24:13 -08001279 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1280
1281 bool empty = 0 == lseek(fd, 0, SEEK_END);
1282 if (!empty) {
1283 ds.AddZipEntry("lshal-debug/" + cleanName + ".txt", path);
1284 }
1285 }
1286
1287 unlink(path.c_str());
1288 }
1289 });
1290
1291 if (!ret.isOk()) {
1292 MYLOGE("Could not list hals from hwservicemanager.\n");
1293 }
1294}
1295
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001296static void dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001297 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001298
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001299 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001300 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001301 DumpBlockStatFiles();
Mark Salyzyn8c8130e2015-12-09 11:21:28 -08001302 dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001303 DumpFile("MEMORY INFO", "/proc/meminfo");
1304 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001305 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Felipe Lemef0292972016-11-22 13:57:05 -08001306 RunCommand("PROCRANK", {"procrank"}, AS_ROOT_20);
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001307 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1308 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1309 DumpFile("SLAB INFO", "/proc/slabinfo");
1310 DumpFile("ZONEINFO", "/proc/zoneinfo");
1311 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1312 DumpFile("BUDDYINFO", "/proc/buddyinfo");
1313 DumpFile("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001314
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001315 DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources");
1316 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
1317 DumpFile("KERNEL SYNC", "/d/sync");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001318
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001319 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001320 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Felipe Lemef0292972016-11-22 13:57:05 -08001321 RunCommand("LIBRANK", {"librank"}, CommandOptions::AS_ROOT);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001322
Andreas Huber69ec3ac2017-03-23 09:47:51 -07001323 if (ds.IsZipping()) {
Steven Moreland44cd9482018-01-04 16:24:13 -08001324 RunCommand("HARDWARE HALS", {"lshal"}, CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1325 DumpHals();
Andreas Huber69ec3ac2017-03-23 09:47:51 -07001326 } else {
Steven Moreland44cd9482018-01-04 16:24:13 -08001327 RunCommand("HARDWARE HALS", {"lshal", "--debug"}, CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
Andreas Huber69ec3ac2017-03-23 09:47:51 -07001328 }
Steven Moreland81b429e2017-01-31 19:50:46 -08001329
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001330 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001331 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001332 struct stat s;
1333 if (stat("/proc/modules", &s) != 0) {
1334 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1335 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001336 RunCommand("LSMOD", {"lsmod"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001337 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001338
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001339 if (__android_logger_property_get_bool(
1340 "ro.logd.kernel", BOOL_DEFAULT_TRUE | BOOL_DEFAULT_FLAG_ENG | BOOL_DEFAULT_FLAG_SVELTE)) {
1341 DoKernelLogcat();
1342 } else {
1343 do_dmesg();
1344 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001345
Felipe Lemef0292972016-11-22 13:57:05 -08001346 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Jeff Brown1dc94e32014-09-11 14:15:27 -07001347 for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES");
1348 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001349 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001350
Ajay Panicker2ff8e872017-04-27 14:04:32 -07001351 /* Dump Bluetooth HCI logs */
1352 ds.AddDir("/data/misc/bluetooth/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001353
Felipe Leme9a523ae2016-10-20 15:10:33 -07001354 if (!ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001355 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001356 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001357 }
1358
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001359 DoLogcat();
Mark Salyzynecc07632015-07-30 14:57:09 -07001360
Felipe Lemee184f662016-10-27 10:04:47 -07001361 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001362
Narayan Kamath8f788292017-05-25 13:20:39 +01001363 // NOTE: tombstones are always added as separate entries in the zip archive
1364 // and are not interspersed with the main report.
Narayan Kamathbd863722017-06-01 18:50:12 +01001365 const bool tombstones_dumped = AddDumps(tombstone_data->begin(), tombstone_data->end(),
1366 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001367 if (!tombstones_dumped) {
1368 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001369 }
1370
Jayachandran Ca94c7172017-06-10 15:08:12 -07001371 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001372
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001373 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001374
Jayachandran Ca94c7172017-06-10 15:08:12 -07001375 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001376
1377 dump_route_tables();
1378
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001379 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1380 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1381 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001382
Vishnu Nair780b1282017-10-10 13:57:24 -07001383 RunDumpsysHigh();
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001384
Elliott Hughes23ccc622017-02-28 10:14:22 -08001385 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001386
Jin Qianf334d662017-10-10 14:41:37 -07001387 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001388
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001389 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001390
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001391 RunCommand("LAST RADIO LOG", {"parse_radio_log", "/proc/last_radio_log"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001392
Colin Crossf45fa6b2012-03-26 12:38:26 -07001393 /* Binder state is expensive to look at as it uses a lot of memory. */
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001394 DumpFile("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
1395 DumpFile("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
1396 DumpFile("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
1397 DumpFile("BINDER STATS", "/sys/kernel/debug/binder/stats");
1398 DumpFile("BINDER STATE", "/sys/kernel/debug/binder/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001399
Vishnu Nair36b4cdb2017-11-17 10:27:05 -08001400 /* Add window and surface trace files. */
1401 if (!PropertiesHelper::IsUserBuild()) {
1402 ds.AddDir(WMTRACE_DATA_DIR, false);
1403 }
1404
Felipe Leme6f674ae2016-11-18 17:10:33 -08001405 ds.DumpstateBoard();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001406
Steven Moreland7440ddb2016-12-15 16:13:39 -08001407 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001408 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1409 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001410 // su does not exist on user builds, so try running without it.
1411 // This way any implementations of vril-dump that do not require
1412 // root can run on user builds.
1413 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001414 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001415 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001416 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001417 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001418 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001419 }
1420
Felipe Lemed8b94e52016-12-08 10:21:44 -08001421 printf("========================================================\n");
1422 printf("== Android Framework Services\n");
1423 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001424
Vishnu Nair780b1282017-10-10 13:57:24 -07001425 RunDumpsysNormal();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001426
Felipe Lemed8b94e52016-12-08 10:21:44 -08001427 printf("========================================================\n");
1428 printf("== Checkins\n");
1429 printf("========================================================\n");
Dianne Hackborn02bea972013-06-26 18:59:09 -07001430
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001431 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1432 RunDumpsys("CHECKIN MEMINFO", {"meminfo", "--checkin"});
1433 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"});
1434 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"});
1435 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"});
1436 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"});
Dianne Hackborn02bea972013-06-26 18:59:09 -07001437
Felipe Lemed8b94e52016-12-08 10:21:44 -08001438 printf("========================================================\n");
1439 printf("== Running Application Activities\n");
1440 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001441
Winson Chung1434a5c2017-02-28 17:09:24 -08001442 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001443
Felipe Lemed8b94e52016-12-08 10:21:44 -08001444 printf("========================================================\n");
1445 printf("== Running Application Services\n");
1446 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001447
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001448 RunDumpsys("APP SERVICES", {"activity", "service", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001449
Felipe Lemed8b94e52016-12-08 10:21:44 -08001450 printf("========================================================\n");
1451 printf("== Running Application Providers\n");
1452 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001453
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001454 RunDumpsys("APP PROVIDERS", {"activity", "provider", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001455
Adrian Roos8b397ab2017-04-04 16:35:44 -07001456 printf("========================================================\n");
1457 printf("== Dropbox crashes\n");
1458 printf("========================================================\n");
1459
1460 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1461 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1462
Felipe Lemed8b94e52016-12-08 10:21:44 -08001463 printf("========================================================\n");
1464 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1465 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1466 printf("========================================================\n");
1467 printf("== dumpstate: done (id %d)\n", ds.id_);
1468 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001469}
1470
mukesh agrawal253dad42018-01-23 21:59:59 -08001471// This method collects common dumpsys for telephony and wifi
1472static void DumpstateRadioCommon() {
Jayachandran Ca94c7172017-06-10 15:08:12 -07001473 DumpIpTablesAsRoot();
1474
1475 if (!DropRootUser()) {
1476 return;
1477 }
1478
1479 do_dmesg();
1480 DoLogcat();
1481 DumpPacketStats();
1482 DoKmsg();
1483 DumpIpAddrAndRules();
1484 dump_route_tables();
1485
1486 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
1487 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08001488}
1489
1490// This method collects dumpsys for telephony debugging only
1491static void DumpstateTelephonyOnly() {
1492 DurationReporter duration_reporter("DUMPSTATE");
1493
1494 DumpstateRadioCommon();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001495
1496 RunCommand("SYSTEM PROPERTIES", {"getprop"});
1497
1498 printf("========================================================\n");
1499 printf("== Android Framework Services\n");
1500 printf("========================================================\n");
1501
Vishnu Nair652cc802017-11-30 15:18:30 -08001502 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1503 SEC_TO_MSEC(10));
1504 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
1505 SEC_TO_MSEC(10));
Jayachandran Ca94c7172017-06-10 15:08:12 -07001506
1507 printf("========================================================\n");
1508 printf("== Running Application Services\n");
1509 printf("========================================================\n");
1510
1511 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
1512
1513 printf("========================================================\n");
Sooraj Sasindran963b04f2018-03-09 13:26:39 -08001514 printf("== Checkins\n");
1515 printf("========================================================\n");
1516
1517 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1518
1519 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07001520 printf("== dumpstate: done (id %d)\n", ds.id_);
1521 printf("========================================================\n");
1522}
1523
mukesh agrawal253dad42018-01-23 21:59:59 -08001524// This method collects dumpsys for wifi debugging only
1525static void DumpstateWifiOnly() {
1526 DurationReporter duration_reporter("DUMPSTATE");
1527
1528 DumpstateRadioCommon();
1529
1530 printf("========================================================\n");
1531 printf("== Android Framework Services\n");
1532 printf("========================================================\n");
1533
1534 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1535 SEC_TO_MSEC(10));
1536 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
1537 SEC_TO_MSEC(10));
1538
1539 printf("========================================================\n");
1540 printf("== dumpstate: done (id %d)\n", ds.id_);
1541 printf("========================================================\n");
1542}
1543
Felipe Leme6f674ae2016-11-18 17:10:33 -08001544void Dumpstate::DumpstateBoard() {
1545 DurationReporter duration_reporter("dumpstate_board()");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001546 printf("========================================================\n");
1547 printf("== Board\n");
1548 printf("========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001549
Chris Phoenix69d92212017-01-24 23:01:13 -08001550 ::android::sp<IDumpstateDevice> dumpstate_device(IDumpstateDevice::getService());
Felipe Leme6f674ae2016-11-18 17:10:33 -08001551 if (dumpstate_device == nullptr) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08001552 MYLOGE("No IDumpstateDevice implementation\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001553 return;
1554 }
1555
1556 if (!IsZipping()) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08001557 MYLOGD("Not dumping board info because it's not a zipped bugreport\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001558 return;
1559 }
1560
Jie Song9fbfad02017-06-20 16:29:42 -07001561 std::string path[NUM_OF_DUMPS];
1562 android::base::unique_fd fd[NUM_OF_DUMPS];
1563 int numFds = 0;
Felipe Leme6f674ae2016-11-18 17:10:33 -08001564
Jie Song9fbfad02017-06-20 16:29:42 -07001565 for (int i = 0; i < NUM_OF_DUMPS; i++) {
1566 path[i] = kDumpstateBoardPath + kDumpstateBoardFiles[i];
1567 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", path[i].c_str());
1568
1569 fd[i] = android::base::unique_fd(
1570 TEMP_FAILURE_RETRY(open(path[i].c_str(),
1571 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1572 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1573 if (fd[i] < 0) {
1574 MYLOGE("Could not open file %s: %s\n", path[i].c_str(), strerror(errno));
1575 return;
1576 } else {
1577 numFds++;
1578 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001579 }
1580
Jie Song9fbfad02017-06-20 16:29:42 -07001581 native_handle_t *handle = native_handle_create(numFds, 0);
Felipe Leme6f674ae2016-11-18 17:10:33 -08001582 if (handle == nullptr) {
1583 MYLOGE("Could not create native_handle\n");
1584 return;
1585 }
Jie Song9fbfad02017-06-20 16:29:42 -07001586
1587 for (int i = 0; i < numFds; i++) {
1588 handle->data[i] = fd[i].release();
1589 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001590
Felipe Lemef0292972016-11-22 13:57:05 -08001591 // TODO: need a timeout mechanism so dumpstate does not hang on device implementation call.
Steven Moreland7440ddb2016-12-15 16:13:39 -08001592 android::hardware::Return<void> status = dumpstate_device->dumpstateBoard(handle);
1593 if (!status.isOk()) {
1594 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
1595 native_handle_close(handle);
1596 native_handle_delete(handle);
1597 return;
1598 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001599
Jie Song9fbfad02017-06-20 16:29:42 -07001600 for (int i = 0; i < numFds; i++) {
1601 struct stat s;
1602 if (fstat(handle->data[i], &s) == -1) {
1603 MYLOGE("Failed to fstat %s: %d\n", kDumpstateBoardFiles[i].c_str(), errno);
1604 } else if (s.st_size > 0) {
1605 AddZipEntry(kDumpstateBoardFiles[i], path[i]);
1606 } else {
1607 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
1608 }
1609 }
1610
Felipe Lemed8b94e52016-12-08 10:21:44 -08001611 printf("*** See dumpstate-board.txt entry ***\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001612
1613 native_handle_close(handle);
1614 native_handle_delete(handle);
1615
Jie Song9fbfad02017-06-20 16:29:42 -07001616 for (int i = 0; i < numFds; i++) {
1617 if (remove(path[i].c_str()) != 0) {
1618 MYLOGE("Could not remove(%s): %s\n", path[i].c_str(), strerror(errno));
1619 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001620 }
1621}
1622
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001623static void ShowUsageAndExit(int exitCode = 1) {
1624 fprintf(stderr,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001625 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file] [-d] [-p] "
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001626 "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
1627 " -h: display this help message\n"
1628 " -b: play sound file instead of vibrate, at beginning of job\n"
1629 " -e: play sound file instead of vibrate, at end of job\n"
1630 " -o: write to file (instead of stdout)\n"
1631 " -d: append date to filename (requires -o)\n"
1632 " -p: capture screenshot to filename.png (requires -o)\n"
1633 " -z: generate zipped file (requires -o)\n"
1634 " -s: write output to control socket (for init)\n"
Takuya Ogawa47f644e2017-12-20 18:09:09 +09001635 " -S: write file location to control socket (for init; requires -o and -z)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001636 " -q: disable vibrate\n"
1637 " -B: send broadcast when finished (requires -o)\n"
1638 " -P: send broadcast when started and update system properties on "
1639 "progress (requires -o and -B)\n"
1640 " -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
1641 "shouldn't be used with -P)\n"
Felipe Lemed071c682016-10-20 16:48:00 -07001642 " -v: prints the dumpstate header and exit\n");
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001643 exit(exitCode);
1644}
1645
1646static void ExitOnInvalidArgs() {
1647 fprintf(stderr, "invalid combination of args\n");
1648 ShowUsageAndExit();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001649}
1650
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08001651static void sig_handler(int) {
Andres Morales2e671bb2014-08-21 12:38:22 -07001652 _exit(EXIT_FAILURE);
John Michelau885f8882013-05-06 16:42:02 -05001653}
1654
Wei Liuf87959e2016-08-26 14:51:42 -07001655static void register_sig_handler() {
1656 struct sigaction sa;
1657 sigemptyset(&sa.sa_mask);
1658 sa.sa_flags = 0;
1659 sa.sa_handler = sig_handler;
1660 sigaction(SIGPIPE, &sa, NULL); // broken pipe
1661 sigaction(SIGSEGV, &sa, NULL); // segment fault
1662 sigaction(SIGINT, &sa, NULL); // ctrl-c
1663 sigaction(SIGTERM, &sa, NULL); // killed
1664 sigaction(SIGQUIT, &sa, NULL); // quit
1665}
1666
Felipe Leme1d486fe2016-10-14 18:06:47 -07001667bool Dumpstate::FinishZipFile() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001668 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07001669 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07001670 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001671 // Final timestamp
1672 char date[80];
1673 time_t the_real_now_please_stand_up = time(nullptr);
1674 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07001675 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001676 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001677
Felipe Leme9a523ae2016-10-20 15:10:33 -07001678 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001679 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08001680 return false;
1681 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07001682 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001683 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08001684 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08001685 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08001686
Felipe Leme0f3fb202016-06-10 17:10:53 -07001687 // Add log file (which contains stderr output) to zip...
1688 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001689 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07001690 MYLOGE("Failed to add dumpstate log to .zip file\n");
1691 return false;
1692 }
1693 // ... and re-opens it for further logging.
Felipe Leme9a523ae2016-10-20 15:10:33 -07001694 redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()));
Felipe Leme0f3fb202016-06-10 17:10:53 -07001695 fprintf(stderr, "\n");
1696
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001697 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07001698 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001699 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001700 return false;
1701 }
1702
Felipe Leme1d486fe2016-10-14 18:06:47 -07001703 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
1704 ds.zip_file.reset(nullptr);
1705
Felipe Lemee9d2c542016-11-15 11:48:26 -08001706 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
1707 if (remove(tmp_path_.c_str()) != 0) {
1708 MYLOGE("Failed to remove temporary file (%s): %s\n", tmp_path_.c_str(), strerror(errno));
Felipe Lemec4eee562016-04-21 15:42:55 -07001709 }
1710
Felipe Leme1e9edc62015-12-21 16:02:13 -08001711 return true;
1712}
Felipe Leme6e01fa62015-11-11 19:35:14 -08001713
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -07001714static std::string SHA256_file_hash(const std::string& filepath) {
Andreas Gampe27cd7b22016-07-18 18:24:05 -07001715 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK
1716 | O_CLOEXEC | O_NOFOLLOW)));
Andreas Gampeaff68432016-07-18 18:01:27 -07001717 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001718 MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
Michal Karpinski4db754f2015-12-11 18:04:32 +00001719 return NULL;
1720 }
1721
1722 SHA256_CTX ctx;
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001723 SHA256_Init(&ctx);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001724
1725 std::vector<uint8_t> buffer(65536);
1726 while (1) {
1727 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
1728 if (bytes_read == 0) {
1729 break;
1730 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001731 MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
Michal Karpinski4db754f2015-12-11 18:04:32 +00001732 return NULL;
1733 }
1734
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001735 SHA256_Update(&ctx, buffer.data(), bytes_read);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001736 }
1737
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001738 uint8_t hash[SHA256_DIGEST_LENGTH];
1739 SHA256_Final(hash, &ctx);
1740
1741 char hash_buffer[SHA256_DIGEST_LENGTH * 2 + 1];
1742 for(size_t i = 0; i < SHA256_DIGEST_LENGTH; i++) {
Michal Karpinskicbbdf732016-01-07 20:45:02 +00001743 sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001744 }
1745 hash_buffer[sizeof(hash_buffer) - 1] = 0;
1746 return std::string(hash_buffer);
1747}
1748
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001749static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) {
1750 // clang-format off
1751 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0",
1752 "--receiver-foreground", "--receiver-include-background", "-a", action};
1753 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08001754
1755 am.insert(am.end(), args.begin(), args.end());
1756
Felipe Leme8d2410e2017-02-08 09:46:08 -08001757 RunCommand("", am,
1758 CommandOptions::WithTimeout(20)
1759 .Log("Sending broadcast: '%s'\n")
1760 .Always()
1761 .DropRoot()
1762 .RedirectStderr()
1763 .Build());
1764}
1765
Felipe Leme35b8cf12017-02-10 15:47:29 -08001766static void Vibrate(int duration_ms) {
1767 // clang-format off
1768 RunCommand("", {"cmd", "vibrator", "vibrate", std::to_string(duration_ms), "dumpstate"},
1769 CommandOptions::WithTimeout(10)
1770 .Log("Vibrate: '%s'\n")
1771 .Always()
1772 .Build());
1773 // clang-format on
1774}
1775
Vishnu Nair20cf5032018-01-05 13:15:49 -08001776/** Main entry point for dumpstate. */
1777int run_main(int argc, char* argv[]) {
Colin Crossf45fa6b2012-03-26 12:38:26 -07001778 int do_add_date = 0;
Felipe Leme6e01fa62015-11-11 19:35:14 -08001779 int do_zip_file = 0;
John Michelau1f794c42012-09-17 11:20:19 -05001780 int do_vibrate = 1;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001781 char* use_outfile = 0;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001782 int use_socket = 0;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001783 int use_control_socket = 0;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001784 int do_fb = 0;
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07001785 int do_broadcast = 0;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001786 int is_remote_mode = 0;
Felipe Lemed071c682016-10-20 16:48:00 -07001787 bool show_header_only = false;
Felipe Leme75876a22016-10-27 16:31:27 -07001788 bool do_start_service = false;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001789 bool telephony_only = false;
mukesh agrawal253dad42018-01-23 21:59:59 -08001790 bool wifi_only = false;
Vishnu Nair20cf5032018-01-05 13:15:49 -08001791 int dup_stdout_fd;
1792 int dup_stderr_fd;
Felipe Leme8fecfdd2016-02-09 10:40:07 -08001793
Colin Crossf45fa6b2012-03-26 12:38:26 -07001794 /* set as high priority, and protect from OOM killer */
1795 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001796
Felipe Lemed071c682016-10-20 16:48:00 -07001797 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001798 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001799 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001800 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001801 } else {
1802 /* fallback to kernels <= 2.6.35 */
1803 oom_adj = fopen("/proc/self/oom_adj", "we");
1804 if (oom_adj) {
1805 fputs("-17", oom_adj);
1806 fclose(oom_adj);
1807 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001808 }
1809
Jeff Brown1dc94e32014-09-11 14:15:27 -07001810 /* parse arguments */
Colin Crossf45fa6b2012-03-26 12:38:26 -07001811 int c;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001812 while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
Colin Crossf45fa6b2012-03-26 12:38:26 -07001813 switch (c) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001814 // clang-format off
Felipe Lemed071c682016-10-20 16:48:00 -07001815 case 'd': do_add_date = 1; break;
1816 case 'z': do_zip_file = 1; break;
1817 case 'o': use_outfile = optarg; break;
1818 case 's': use_socket = 1; break;
1819 case 'S': use_control_socket = 1; break;
1820 case 'v': show_header_only = true; break;
1821 case 'q': do_vibrate = 0; break;
1822 case 'p': do_fb = 1; break;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001823 case 'P': ds.update_progress_ = true; break;
Felipe Lemed071c682016-10-20 16:48:00 -07001824 case 'R': is_remote_mode = 1; break;
1825 case 'B': do_broadcast = 1; break;
1826 case 'V': break; // compatibility no-op
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001827 case 'h':
1828 ShowUsageAndExit(0);
1829 break;
1830 default:
1831 fprintf(stderr, "Invalid option: %c\n", c);
1832 ShowUsageAndExit();
Felipe Lemee844a9d2016-09-21 15:01:39 -07001833 // clang-format on
Colin Crossf45fa6b2012-03-26 12:38:26 -07001834 }
1835 }
1836
Felipe Lemed071c682016-10-20 16:48:00 -07001837 // TODO: use helper function to convert argv into a string
1838 for (int i = 0; i < argc; i++) {
1839 ds.args_ += argv[i];
1840 if (i < argc - 1) {
1841 ds.args_ += " ";
1842 }
1843 }
1844
1845 ds.extra_options_ = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001846 if (!ds.extra_options_.empty()) {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001847 // Framework uses a system property to override some command-line args.
1848 // Currently, it contains the type of the requested bugreport.
Felipe Leme9a523ae2016-10-20 15:10:33 -07001849 if (ds.extra_options_ == "bugreportplus") {
Felipe Leme75876a22016-10-27 16:31:27 -07001850 // Currently, the dumpstate binder is only used by Shell to update progress.
1851 do_start_service = true;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001852 ds.update_progress_ = true;
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001853 do_fb = 0;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001854 } else if (ds.extra_options_ == "bugreportremote") {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001855 do_vibrate = 0;
1856 is_remote_mode = 1;
1857 do_fb = 0;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001858 } else if (ds.extra_options_ == "bugreportwear") {
lingfan44612512018-02-27 11:32:11 -08001859 do_start_service = true;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001860 ds.update_progress_ = true;
Alain Vongsouvanh46edde32017-10-25 16:16:24 -07001861 do_zip_file = 1;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001862 } else if (ds.extra_options_ == "bugreporttelephony") {
1863 telephony_only = true;
mukesh agrawal253dad42018-01-23 21:59:59 -08001864 } else if (ds.extra_options_ == "bugreportwifi") {
1865 wifi_only = true;
1866 do_zip_file = 1;
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001867 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001868 MYLOGE("Unknown extra option: %s\n", ds.extra_options_.c_str());
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001869 }
1870 // Reset the property
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001871 android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, "");
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001872 }
1873
Naveen Kallab53a1c92017-03-16 18:17:25 -07001874 ds.notification_title = android::base::GetProperty(PROPERTY_EXTRA_TITLE, "");
1875 if (!ds.notification_title.empty()) {
1876 // Reset the property
1877 android::base::SetProperty(PROPERTY_EXTRA_TITLE, "");
1878
1879 ds.notification_description = android::base::GetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
1880 if (!ds.notification_description.empty()) {
1881 // Reset the property
1882 android::base::SetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
1883 }
1884 MYLOGD("notification (title: %s, description: %s)\n",
1885 ds.notification_title.c_str(), ds.notification_description.c_str());
1886 }
1887
Felipe Leme9a523ae2016-10-20 15:10:33 -07001888 if ((do_zip_file || do_add_date || ds.update_progress_ || do_broadcast) && !use_outfile) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001889 ExitOnInvalidArgs();
Felipe Leme6e01fa62015-11-11 19:35:14 -08001890 }
1891
Felipe Leme2628e9e2016-04-12 16:36:51 -07001892 if (use_control_socket && !do_zip_file) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001893 ExitOnInvalidArgs();
Felipe Leme2628e9e2016-04-12 16:36:51 -07001894 }
1895
Felipe Leme9a523ae2016-10-20 15:10:33 -07001896 if (ds.update_progress_ && !do_broadcast) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001897 ExitOnInvalidArgs();
Felipe Leme71bbfc52015-11-23 14:14:51 -08001898 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001899
Felipe Leme9a523ae2016-10-20 15:10:33 -07001900 if (is_remote_mode && (ds.update_progress_ || !do_broadcast || !do_zip_file || !do_add_date)) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001901 ExitOnInvalidArgs();
Michal Karpinski4db754f2015-12-11 18:04:32 +00001902 }
1903
Felipe Lemed071c682016-10-20 16:48:00 -07001904 if (ds.version_ == VERSION_DEFAULT) {
1905 ds.version_ = VERSION_CURRENT;
Felipe Leme809d74e2016-02-02 12:57:00 -08001906 }
1907
Vishnu Nair64afc022018-02-01 15:29:34 -08001908 if (ds.version_ != VERSION_CURRENT && ds.version_ != VERSION_SPLIT_ANR) {
1909 MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s')\n",
1910 ds.version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
1911 VERSION_SPLIT_ANR.c_str());
Felipe Lemed071c682016-10-20 16:48:00 -07001912 exit(1);
1913 }
1914
1915 if (show_header_only) {
1916 ds.PrintHeader();
1917 exit(0);
1918 }
1919
Felipe Leme7447d7c2016-11-03 18:12:22 -07001920 /* redirect output if needed */
1921 bool is_redirecting = !use_socket && use_outfile;
1922
1923 // TODO: temporarily set progress until it's part of the Dumpstate constructor
1924 std::string stats_path =
1925 is_redirecting ? android::base::StringPrintf("%s/dumpstate-stats.txt", dirname(use_outfile))
1926 : "";
1927 ds.progress_.reset(new Progress(stats_path));
1928
Felipe Lemed071c682016-10-20 16:48:00 -07001929 /* gets the sequential id */
Felipe Leme7447d7c2016-11-03 18:12:22 -07001930 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
Felipe Lemed071c682016-10-20 16:48:00 -07001931 ds.id_ = ++last_id;
1932 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
1933
1934 MYLOGI("begin\n");
1935
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08001936 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07001937
Felipe Leme75876a22016-10-27 16:31:27 -07001938 if (do_start_service) {
1939 MYLOGI("Starting 'dumpstate' service\n");
1940 android::status_t ret;
1941 if ((ret = android::os::DumpstateService::Start()) != android::OK) {
1942 MYLOGE("Unable to start DumpstateService: %d\n", ret);
1943 }
1944 }
1945
Felipe Lemef0292972016-11-22 13:57:05 -08001946 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07001947 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
1948 }
1949
Felipe Leme7447d7c2016-11-03 18:12:22 -07001950 MYLOGI("dumpstate info: id=%d, args='%s', extra_options= %s)\n", ds.id_, ds.args_.c_str(),
Felipe Lemed071c682016-10-20 16:48:00 -07001951 ds.extra_options_.c_str());
1952
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001953 MYLOGI("bugreport format version: %s\n", ds.version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08001954
Felipe Leme9a523ae2016-10-20 15:10:33 -07001955 ds.do_early_screenshot_ = ds.update_progress_;
Felipe Lemee338bf62015-12-07 14:03:50 -08001956
Christopher Ferrised9354f2014-10-01 17:35:01 -07001957 // If we are going to use a socket, do it as early as possible
1958 // to avoid timeouts from bugreport.
1959 if (use_socket) {
1960 redirect_to_socket(stdout, "dumpstate");
1961 }
1962
Felipe Leme2628e9e2016-04-12 16:36:51 -07001963 if (use_control_socket) {
1964 MYLOGD("Opening control socket\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001965 ds.control_socket_fd_ = open_socket("dumpstate");
1966 ds.update_progress_ = 1;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001967 }
1968
Felipe Leme71bbfc52015-11-23 14:14:51 -08001969 if (is_redirecting) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001970 ds.bugreport_dir_ = dirname(use_outfile);
Felipe Lemef8124bd2016-12-15 08:54:22 -08001971 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
Ian Pedowitz570e6ec2017-03-17 22:36:53 -07001972 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Felipe Lemef8124bd2016-12-15 08:54:22 -08001973 ds.base_name_ = android::base::StringPrintf("%s-%s-%s", basename(use_outfile),
1974 device_name.c_str(), build_id.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08001975 if (do_add_date) {
1976 char date[80];
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001977 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001978 ds.name_ = date;
Felipe Lemead5f6c42015-11-30 14:26:46 -08001979 } else {
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001980 ds.name_ = "undated";
Felipe Leme71bbfc52015-11-23 14:14:51 -08001981 }
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001982
1983 if (telephony_only) {
1984 ds.base_name_ += "-telephony";
mukesh agrawal253dad42018-01-23 21:59:59 -08001985 } else if (wifi_only) {
1986 ds.base_name_ += "-wifi";
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001987 }
1988
Felipe Leme71bbfc52015-11-23 14:14:51 -08001989 if (do_fb) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001990 ds.screenshot_path_ = ds.GetPath(".png");
Felipe Leme71bbfc52015-11-23 14:14:51 -08001991 }
Felipe Leme9a523ae2016-10-20 15:10:33 -07001992 ds.tmp_path_ = ds.GetPath(".tmp");
Felipe Leme75876a22016-10-27 16:31:27 -07001993 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
Felipe Leme71bbfc52015-11-23 14:14:51 -08001994
Felipe Lemee844a9d2016-09-21 15:01:39 -07001995 MYLOGD(
1996 "Bugreport dir: %s\n"
1997 "Base name: %s\n"
1998 "Suffix: %s\n"
1999 "Log path: %s\n"
2000 "Temporary path: %s\n"
2001 "Screenshot path: %s\n",
Felipe Leme9a523ae2016-10-20 15:10:33 -07002002 ds.bugreport_dir_.c_str(), ds.base_name_.c_str(), ds.name_.c_str(),
2003 ds.log_path_.c_str(), ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08002004
Felipe Leme1e9edc62015-12-21 16:02:13 -08002005 if (do_zip_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002006 ds.path_ = ds.GetPath(".zip");
2007 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2008 create_parent_dirs(ds.path_.c_str());
2009 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
Felipe Leme1d486fe2016-10-14 18:06:47 -07002010 if (ds.zip_file == nullptr) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002011 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002012 do_zip_file = 0;
2013 } else {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002014 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002015 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07002016 ds.AddTextZipEntry("version.txt", ds.version_);
Felipe Leme1e9edc62015-12-21 16:02:13 -08002017 }
2018
Felipe Leme9a523ae2016-10-20 15:10:33 -07002019 if (ds.update_progress_) {
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07002020 if (do_broadcast) {
2021 // clang-format off
Christopher Tatecfaa07a2017-01-23 12:20:21 -08002022
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07002023 std::vector<std::string> am_args = {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002024 "--receiver-permission", "android.permission.DUMP",
Felipe Leme2b9b06c2016-10-14 09:13:06 -07002025 "--es", "android.intent.extra.NAME", ds.name_,
Felipe Lemee844a9d2016-09-21 15:01:39 -07002026 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
Felipe Leme75876a22016-10-27 16:31:27 -07002027 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
Felipe Leme7447d7c2016-11-03 18:12:22 -07002028 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07002029 };
2030 // clang-format on
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002031 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07002032 }
Felipe Lemeaabfcae2016-07-29 09:49:04 -07002033 if (use_control_socket) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002034 dprintf(ds.control_socket_fd_, "BEGIN:%s\n", ds.path_.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07002035 }
Felipe Leme71bbfc52015-11-23 14:14:51 -08002036 }
2037 }
2038
Nick Kralevichf3599b32016-01-25 15:05:16 -08002039 /* read /proc/cmdline before dropping root */
2040 FILE *cmdline = fopen("/proc/cmdline", "re");
2041 if (cmdline) {
2042 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
2043 fclose(cmdline);
2044 }
2045
John Michelau1f794c42012-09-17 11:20:19 -05002046 if (do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08002047 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05002048 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002049
Felipe Leme9a523ae2016-10-20 15:10:33 -07002050 if (do_fb && ds.do_early_screenshot_) {
2051 if (ds.screenshot_path_.empty()) {
Felipe Leme3634a1e2015-12-09 10:11:47 -08002052 // should not have happened
Felipe Lemecbce55d2016-02-08 09:53:18 -08002053 MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
Felipe Leme3634a1e2015-12-09 10:11:47 -08002054 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002055 MYLOGI("taking early screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002056 ds.TakeScreenshot();
Felipe Lemee338bf62015-12-07 14:03:50 -08002057 }
2058 }
2059
Felipe Leme1e9edc62015-12-21 16:02:13 -08002060 if (do_zip_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002061 if (chown(ds.path_.c_str(), AID_SHELL, AID_SHELL)) {
2062 MYLOGE("Unable to change ownership of zip file %s: %s\n", ds.path_.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07002063 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002064 }
2065 }
2066
Felipe Leme71bbfc52015-11-23 14:14:51 -08002067 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002068 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
Felipe Leme9a523ae2016-10-20 15:10:33 -07002069 redirect_to_file(stderr, const_cast<char*>(ds.log_path_.c_str()));
2070 if (chown(ds.log_path_.c_str(), AID_SHELL, AID_SHELL)) {
2071 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n",
2072 ds.log_path_.c_str(), strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08002073 }
Vishnu Nair20cf5032018-01-05 13:15:49 -08002074 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
Felipe Leme6e01fa62015-11-11 19:35:14 -08002075 /* TODO: rather than generating a text file now and zipping it later,
2076 it would be more efficient to redirect stdout to the zip entry
2077 directly, but the libziparchive doesn't support that option yet. */
Felipe Leme9a523ae2016-10-20 15:10:33 -07002078 redirect_to_file(stdout, const_cast<char*>(ds.tmp_path_.c_str()));
2079 if (chown(ds.tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Leme6fe9db62016-02-12 09:04:16 -08002080 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
Felipe Leme9a523ae2016-10-20 15:10:33 -07002081 ds.tmp_path_.c_str(), strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08002082 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002083 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08002084
2085 // Don't buffer stdout
2086 setvbuf(stdout, nullptr, _IONBF, 0);
2087
Felipe Leme608385d2016-02-01 10:35:38 -08002088 // NOTE: there should be no stdout output until now, otherwise it would break the header.
2089 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08002090 // duration is logged into MYLOG instead.
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002091 ds.PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07002092
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002093 if (telephony_only) {
Jayachandran Ca94c7172017-06-10 15:08:12 -07002094 DumpstateTelephonyOnly();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002095 ds.DumpstateBoard();
mukesh agrawal253dad42018-01-23 21:59:59 -08002096 } else if (wifi_only) {
2097 DumpstateWifiOnly();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002098 } else {
2099 // Dumps systrace right away, otherwise it will be filled with unnecessary events.
2100 // First try to dump anrd trace if the daemon is running. Otherwise, dump
2101 // the raw trace.
2102 if (!dump_anrd_trace()) {
2103 dump_systrace();
2104 }
2105
2106 // Invoking the following dumpsys calls before dump_traces() to try and
2107 // keep the system stats as close to its initial state as possible.
Vishnu Nair780b1282017-10-10 13:57:24 -07002108 RunDumpsysCritical();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002109
2110 // TODO: Drop root user and move into dumpstate() once b/28633932 is fixed.
2111 dump_raft();
2112
2113 /* collect stack traces from Dalvik and native processes (needs root) */
2114 dump_traces_path = dump_traces();
2115
2116 /* Run some operations that require root. */
Narayan Kamathbd863722017-06-01 18:50:12 +01002117 tombstone_data.reset(GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping()));
2118 anr_data.reset(GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping()));
Narayan Kamath8f788292017-05-25 13:20:39 +01002119
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002120 ds.AddDir(RECOVERY_DIR, true);
2121 ds.AddDir(RECOVERY_DATA_DIR, true);
2122 ds.AddDir(LOGPERSIST_DATA_DIR, false);
2123 if (!PropertiesHelper::IsUserBuild()) {
2124 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
2125 ds.AddDir(PROFILE_DATA_DIR_REF, true);
2126 }
2127 add_mountinfo();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002128 DumpIpTablesAsRoot();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002129
2130 // Capture any IPSec policies in play. No keys are exposed here.
2131 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"},
2132 CommandOptions::WithTimeout(10).Build());
2133
2134 // Run ss as root so we can see socket marks.
2135 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"},
2136 CommandOptions::WithTimeout(10).Build());
2137
Jin Qian3cd671e2017-09-27 18:50:04 -07002138 // Run iotop as root to show top 100 IO threads
2139 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
2140
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002141 if (!DropRootUser()) {
2142 return -1;
2143 }
2144
2145 dumpstate();
Zhengyin Qian068ecc72016-08-10 16:48:14 -07002146 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07002147
Felipe Leme55b42a62015-11-10 17:39:08 -08002148 /* close output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08002149 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002150 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07002151 }
2152
Felipe Leme6e01fa62015-11-11 19:35:14 -08002153 /* rename or zip the (now complete) .tmp file to its final location */
2154 if (use_outfile) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08002155
2156 /* check if user changed the suffix using system properties */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07002157 std::string name = android::base::GetProperty(
Felipe Leme75876a22016-10-27 16:31:27 -07002158 android::base::StringPrintf("dumpstate.%d.name", ds.pid_), "");
Felipe Lemead5f6c42015-11-30 14:26:46 -08002159 bool change_suffix= false;
Felipe Leme96c2bbb2016-09-26 09:21:21 -07002160 if (!name.empty()) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08002161 /* must whitelist which characters are allowed, otherwise it could cross directories */
2162 std::regex valid_regex("^[-_a-zA-Z0-9]+$");
Felipe Leme96c2bbb2016-09-26 09:21:21 -07002163 if (std::regex_match(name.c_str(), valid_regex)) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08002164 change_suffix = true;
2165 } else {
Felipe Leme96c2bbb2016-09-26 09:21:21 -07002166 MYLOGE("invalid suffix provided by user: %s\n", name.c_str());
Felipe Lemead5f6c42015-11-30 14:26:46 -08002167 }
2168 }
2169 if (change_suffix) {
Felipe Leme2b9b06c2016-10-14 09:13:06 -07002170 MYLOGI("changing suffix from %s to %s\n", ds.name_.c_str(), name.c_str());
2171 ds.name_ = name;
Felipe Leme9a523ae2016-10-20 15:10:33 -07002172 if (!ds.screenshot_path_.empty()) {
2173 std::string new_screenshot_path = ds.GetPath(".png");
2174 if (rename(ds.screenshot_path_.c_str(), new_screenshot_path.c_str())) {
2175 MYLOGE("rename(%s, %s): %s\n", ds.screenshot_path_.c_str(),
2176 new_screenshot_path.c_str(), strerror(errno));
Felipe Lemead5f6c42015-11-30 14:26:46 -08002177 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002178 ds.screenshot_path_ = new_screenshot_path;
Felipe Lemead5f6c42015-11-30 14:26:46 -08002179 }
2180 }
2181 }
2182
Felipe Leme6e01fa62015-11-11 19:35:14 -08002183 bool do_text_file = true;
2184 if (do_zip_file) {
Felipe Leme1d486fe2016-10-14 18:06:47 -07002185 if (!ds.FinishZipFile()) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002186 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Felipe Leme6e01fa62015-11-11 19:35:14 -08002187 do_text_file = true;
2188 } else {
2189 do_text_file = false;
Felipe Leme91274352016-02-26 15:03:52 -08002190 // Since zip file is already created, it needs to be renamed.
Felipe Leme9a523ae2016-10-20 15:10:33 -07002191 std::string new_path = ds.GetPath(".zip");
2192 if (ds.path_ != new_path) {
2193 MYLOGD("Renaming zip file from %s to %s\n", ds.path_.c_str(), new_path.c_str());
2194 if (rename(ds.path_.c_str(), new_path.c_str())) {
2195 MYLOGE("rename(%s, %s): %s\n", ds.path_.c_str(), new_path.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07002196 strerror(errno));
Felipe Leme91274352016-02-26 15:03:52 -08002197 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002198 ds.path_ = new_path;
Felipe Leme91274352016-02-26 15:03:52 -08002199 }
2200 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08002201 }
2202 }
2203 if (do_text_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002204 ds.path_ = ds.GetPath(".txt");
2205 MYLOGD("Generating .txt bugreport at %s from %s\n", ds.path_.c_str(),
2206 ds.tmp_path_.c_str());
2207 if (rename(ds.tmp_path_.c_str(), ds.path_.c_str())) {
2208 MYLOGE("rename(%s, %s): %s\n", ds.tmp_path_.c_str(), ds.path_.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07002209 strerror(errno));
Felipe Leme9a523ae2016-10-20 15:10:33 -07002210 ds.path_.clear();
Felipe Leme6e01fa62015-11-11 19:35:14 -08002211 }
2212 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07002213 if (use_control_socket) {
2214 if (do_text_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002215 dprintf(ds.control_socket_fd_,
Felipe Lemee844a9d2016-09-21 15:01:39 -07002216 "FAIL:could not create zip file, check %s "
2217 "for more details\n",
Felipe Leme9a523ae2016-10-20 15:10:33 -07002218 ds.log_path_.c_str());
Felipe Leme2628e9e2016-04-12 16:36:51 -07002219 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002220 dprintf(ds.control_socket_fd_, "OK:%s\n", ds.path_.c_str());
Felipe Leme2628e9e2016-04-12 16:36:51 -07002221 }
2222 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002223 }
2224
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002225 /* vibrate a few but shortly times to let user know it's finished */
Takuya Ogawa47f644e2017-12-20 18:09:09 +09002226 if (do_vibrate) {
2227 for (int i = 0; i < 3; i++) {
2228 Vibrate(75);
2229 usleep((75 + 50) * 1000);
2230 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002231 }
2232
Jeff Brown1dc94e32014-09-11 14:15:27 -07002233 /* tell activity manager we're done */
Felipe Leme71bbfc52015-11-23 14:14:51 -08002234 if (do_broadcast) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002235 if (!ds.path_.empty()) {
2236 MYLOGI("Final bugreport path: %s\n", ds.path_.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07002237 // clang-format off
Christopher Tatecfaa07a2017-01-23 12:20:21 -08002238
Felipe Leme36b3f6f2015-11-19 15:41:04 -08002239 std::vector<std::string> am_args = {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002240 "--receiver-permission", "android.permission.DUMP",
Felipe Lemee844a9d2016-09-21 15:01:39 -07002241 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
Felipe Leme75876a22016-10-27 16:31:27 -07002242 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
Felipe Leme7447d7c2016-11-03 18:12:22 -07002243 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
Felipe Leme9a523ae2016-10-20 15:10:33 -07002244 "--es", "android.intent.extra.BUGREPORT", ds.path_,
2245 "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_
Felipe Leme36b3f6f2015-11-19 15:41:04 -08002246 };
Felipe Lemeaabfcae2016-07-29 09:49:04 -07002247 // clang-format on
Felipe Leme36b3f6f2015-11-19 15:41:04 -08002248 if (do_fb) {
2249 am_args.push_back("--es");
2250 am_args.push_back("android.intent.extra.SCREENSHOT");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002251 am_args.push_back(ds.screenshot_path_);
Felipe Leme36b3f6f2015-11-19 15:41:04 -08002252 }
Naveen Kallab53a1c92017-03-16 18:17:25 -07002253 if (!ds.notification_title.empty()) {
2254 am_args.push_back("--es");
2255 am_args.push_back("android.intent.extra.TITLE");
2256 am_args.push_back(ds.notification_title);
2257 if (!ds.notification_description.empty()) {
2258 am_args.push_back("--es");
2259 am_args.push_back("android.intent.extra.DESCRIPTION");
2260 am_args.push_back(ds.notification_description);
2261 }
2262 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00002263 if (is_remote_mode) {
2264 am_args.push_back("--es");
2265 am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002266 am_args.push_back(SHA256_file_hash(ds.path_));
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002267 SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED",
2268 am_args);
Michal Karpinski4db754f2015-12-11 18:04:32 +00002269 } else {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002270 SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args);
Michal Karpinski4db754f2015-12-11 18:04:32 +00002271 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08002272 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002273 MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
Felipe Leme6e01fa62015-11-11 19:35:14 -08002274 }
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07002275 }
2276
Felipe Leme7447d7c2016-11-03 18:12:22 -07002277 MYLOGD("Final progress: %d/%d (estimated %d)\n", ds.progress_->Get(), ds.progress_->GetMax(),
2278 ds.progress_->GetInitialMax());
2279 ds.progress_->Save();
2280 MYLOGI("done (id %d)\n", ds.id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002281
Felipe Leme107a05f2016-03-08 15:11:15 -08002282 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002283 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08002284 }
2285
Felipe Leme9a523ae2016-10-20 15:10:33 -07002286 if (use_control_socket && ds.control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07002287 MYLOGD("Closing control socket\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002288 close(ds.control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07002289 }
2290
Narayan Kamath6b9516c2017-10-27 11:15:51 +01002291 CloseDumpFds(tombstone_data.get());
2292 CloseDumpFds(anr_data.get());
2293
Colin Crossf45fa6b2012-03-26 12:38:26 -07002294 return 0;
2295}