blob: 4b67d8f1a03bb0f783dfddbf6fc5cd892d994b59 [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>
Christopher Ferris7dc7f322014-07-22 16:08:19 -070028#include <sys/prctl.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070029#include <sys/resource.h>
30#include <sys/stat.h>
31#include <sys/time.h>
32#include <sys/wait.h>
33#include <unistd.h>
Narayan Kamath8f788292017-05-25 13:20:39 +010034#include <memory>
35#include <regex>
36#include <set>
37#include <string>
38#include <vector>
Colin Crossf45fa6b2012-03-26 12:38:26 -070039
Felipe Leme96c2bbb2016-09-26 09:21:21 -070040#include <android-base/file.h>
41#include <android-base/properties.h>
Elliott Hughes9dc117c2015-12-07 14:21:50 -080042#include <android-base/stringprintf.h>
Naveen Kalla058e1e82016-10-19 21:38:44 -070043#include <android-base/strings.h>
Andreas Gampeaff68432016-07-18 18:01:27 -070044#include <android-base/unique_fd.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080045#include <android/hardware/dumpstate/1.0/IDumpstateDevice.h>
46#include <cutils/native_handle.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070047#include <cutils/properties.h>
Felipe Leme75876a22016-10-27 16:31:27 -070048#include <openssl/sha.h>
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070049#include <private/android_filesystem_config.h>
50#include <private/android_logger.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070051
Felipe Lemef0292972016-11-22 13:57:05 -080052#include "DumpstateInternal.h"
Felipe Leme75876a22016-10-27 16:31:27 -070053#include "DumpstateService.h"
Colin Crossf45fa6b2012-03-26 12:38:26 -070054#include "dumpstate.h"
Felipe Leme6e01fa62015-11-11 19:35:14 -080055
Steven Morelandcb7ef822016-11-29 13:20:37 -080056using ::android::hardware::dumpstate::V1_0::IDumpstateDevice;
Steven Morelandcb7ef822016-11-29 13:20:37 -080057
Felipe Leme47e9be22016-12-21 15:37:07 -080058// TODO: remove once moved to namespace
59using android::os::dumpstate::CommandOptions;
60using android::os::dumpstate::DumpFileToFd;
61using android::os::dumpstate::PropertiesHelper;
62using android::os::dumpstate::GetPidByName;
63
Colin Crossf45fa6b2012-03-26 12:38:26 -070064/* read before root is shed */
65static char cmdline_buf[16384] = "(unknown)";
66static const char *dump_traces_path = NULL;
67
Felipe Leme1d486fe2016-10-14 18:06:47 -070068// TODO: variables and functions below should be part of dumpstate object
69
Felipe Leme635ca312016-01-05 14:23:02 -080070static std::set<std::string> mount_points;
71void add_mountinfo();
Felipe Leme78f2c862015-12-21 09:55:22 -080072
Todd Poynor2a83daa2013-11-22 15:44:22 -080073#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
Mark Salyzyn7d0a7622016-06-24 14:06:15 -070074#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
Wei Wang509bb5d2017-06-09 14:42:12 -070075#define BLK_DEV_SYS_DIR "/sys/block"
Todd Poynor2a83daa2013-11-22 15:44:22 -080076
Wei Liu341938b2016-04-27 16:18:17 -070077#define RAFT_DIR "/data/misc/raft"
Felipe Lemee82a27d2016-01-05 13:35:44 -080078#define RECOVERY_DIR "/cache/recovery"
Mark Salyzynd6ab0112016-03-25 12:56:39 -070079#define RECOVERY_DATA_DIR "/data/misc/recovery"
Mark Salyzyn4d42dea2016-04-01 10:03:14 -070080#define LOGPERSIST_DATA_DIR "/data/misc/logd"
David Brazdild2991962016-06-03 14:40:44 +010081#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
82#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
Erik Kline08165202016-05-30 11:55:44 +090083#define WLUTIL "/vendor/xbin/wlutil"
Vishnu Nair36b4cdb2017-11-17 10:27:05 -080084#define WMTRACE_DATA_DIR "/data/misc/wmtrace"
Christopher Ferris7dc7f322014-07-22 16:08:19 -070085
Narayan Kamath8f788292017-05-25 13:20:39 +010086// TODO(narayan): Since this information has to be kept in sync
87// with tombstoned, we should just put it in a common header.
88//
89// File: system/core/debuggerd/tombstoned/tombstoned.cpp
Narayan Kamathbd863722017-06-01 18:50:12 +010090static const std::string TOMBSTONE_DIR = "/data/tombstones/";
91static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
92static const std::string ANR_DIR = "/data/anr/";
93static const std::string ANR_FILE_PREFIX = "anr_";
Christopher Ferris7dc7f322014-07-22 16:08:19 -070094
Narayan Kamath8f788292017-05-25 13:20:39 +010095struct DumpData {
96 std::string name;
97 int fd;
98 time_t mtime;
99};
100
101static bool operator<(const DumpData& d1, const DumpData& d2) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100102 return d1.mtime > d2.mtime;
Narayan Kamath8f788292017-05-25 13:20:39 +0100103}
104
105static std::unique_ptr<std::vector<DumpData>> tombstone_data;
106static std::unique_ptr<std::vector<DumpData>> anr_data;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700107
Felipe Lemee844a9d2016-09-21 15:01:39 -0700108// TODO: temporary variables and functions used during C++ refactoring
109static Dumpstate& ds = Dumpstate::GetInstance();
Felipe Leme678727a2016-09-21 17:22:11 -0700110static int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand,
111 const CommandOptions& options = CommandOptions::DEFAULT) {
112 return ds.RunCommand(title, fullCommand, options);
113}
114static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
Felipe Lemebda15a02016-11-16 17:48:25 -0800115 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
Vishnu Nair6921f802017-11-22 09:17:23 -0800116 long dumpsysTimeoutMs = 0) {
117 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs);
Felipe Leme678727a2016-09-21 17:22:11 -0700118}
119static int DumpFile(const std::string& title, const std::string& path) {
120 return ds.DumpFile(title, path);
121}
Felipe Lemee82a27d2016-01-05 13:35:44 -0800122
Felipe Lemee844a9d2016-09-21 15:01:39 -0700123// Relative directory (inside the zip) for all files copied as-is into the bugreport.
124static const std::string ZIP_ROOT_DIR = "FS";
125
Steven Moreland7440ddb2016-12-15 16:13:39 -0800126// Must be hardcoded because dumpstate HAL implementation need SELinux access to it
Jie Song9fbfad02017-06-20 16:29:42 -0700127static const std::string kDumpstateBoardPath = "/bugreports/";
128static const std::string kDumpstateBoardFiles[] = {
129 "dumpstate_board.txt",
Felipe Leme95d6ca52017-08-01 16:35:56 -0700130 "dumpstate_board.bin"
Jie Song9fbfad02017-06-20 16:29:42 -0700131};
132static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
133
Andreas Huber69ec3ac2017-03-23 09:47:51 -0700134static const std::string kLsHalDebugPath = "/bugreports/dumpstate_lshal.txt";
Steven Moreland7440ddb2016-12-15 16:13:39 -0800135
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700136static constexpr char PROPERTY_EXTRA_OPTIONS[] = "dumpstate.options";
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700137static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Lemed071c682016-10-20 16:48:00 -0700138static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
Naveen Kallab53a1c92017-03-16 18:17:25 -0700139static constexpr char PROPERTY_EXTRA_TITLE[] = "dumpstate.options.title";
140static constexpr char PROPERTY_EXTRA_DESCRIPTION[] = "dumpstate.options.description";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700141
Felipe Lemef0292972016-11-22 13:57:05 -0800142static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
143
Narayan Kamath8f788292017-05-25 13:20:39 +0100144/*
Narayan Kamathbd863722017-06-01 18:50:12 +0100145 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
146 * The returned vector is sorted by the mtimes of the dumps. If |limit_by_mtime|
147 * is set, the vector only contains files that were written in the last 30 minutes.
Andreas Gamped0d76952017-08-22 13:08:37 -0700148 * If |limit_by_count| is set, the vector only contains the ten latest files.
Narayan Kamath8f788292017-05-25 13:20:39 +0100149 */
Narayan Kamathbd863722017-06-01 18:50:12 +0100150static std::vector<DumpData>* GetDumpFds(const std::string& dir_path,
151 const std::string& file_prefix,
Andreas Gamped0d76952017-08-22 13:08:37 -0700152 bool limit_by_mtime,
153 bool limit_by_count = true) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100154 const time_t thirty_minutes_ago = ds.now_ - 60 * 30;
155
Narayan Kamath8f788292017-05-25 13:20:39 +0100156 std::unique_ptr<std::vector<DumpData>> dump_data(new std::vector<DumpData>());
Narayan Kamathbd863722017-06-01 18:50:12 +0100157 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100158
Narayan Kamathbd863722017-06-01 18:50:12 +0100159 struct dirent* entry = nullptr;
160 while ((entry = readdir(dump_dir.get()))) {
161 if (entry->d_type != DT_REG) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100162 continue;
163 }
164
Narayan Kamathbd863722017-06-01 18:50:12 +0100165 const std::string base_name(entry->d_name);
166 if (base_name.find(file_prefix) != 0) {
167 continue;
168 }
169
170 const std::string abs_path = dir_path + base_name;
171 android::base::unique_fd fd(
172 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
173 if (fd == -1) {
174 MYLOGW("Unable to open dump file: %s %s\n", abs_path.c_str(), strerror(errno));
175 break;
176 }
177
178 struct stat st = {};
179 if (fstat(fd, &st) == -1) {
180 MYLOGW("Unable to stat dump file: %s %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamath8f788292017-05-25 13:20:39 +0100181 continue;
182 }
183
184 if (limit_by_mtime && st.st_mtime >= thirty_minutes_ago) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100185 MYLOGI("Excluding stale dump file: %s\n", abs_path.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100186 continue;
187 }
188
Narayan Kamathbd863722017-06-01 18:50:12 +0100189 DumpData data = {.name = abs_path, .fd = fd.release(), .mtime = st.st_mtime};
Narayan Kamath8f788292017-05-25 13:20:39 +0100190
191 dump_data->push_back(data);
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700192 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100193
194 std::sort(dump_data->begin(), dump_data->end());
195
Andreas Gamped0d76952017-08-22 13:08:37 -0700196 if (limit_by_count && dump_data->size() > 10) {
197 dump_data->erase(dump_data->begin() + 10, dump_data->end());
198 }
199
Narayan Kamath8f788292017-05-25 13:20:39 +0100200 return dump_data.release();
201}
202
Narayan Kamathbd863722017-06-01 18:50:12 +0100203static bool AddDumps(const std::vector<DumpData>::const_iterator start,
204 const std::vector<DumpData>::const_iterator end,
205 const char* type_name, const bool add_to_zip) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100206 bool dumped = false;
Narayan Kamathbd863722017-06-01 18:50:12 +0100207 for (auto it = start; it != end; ++it) {
208 const std::string& name = it->name;
209 const int fd = it->fd;
Narayan Kamath8f788292017-05-25 13:20:39 +0100210 dumped = true;
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100211
212 // Seek to the beginning of the file before dumping any data. A given
213 // DumpData entry might be dumped multiple times in the report.
214 //
215 // For example, the most recent ANR entry is dumped to the body of the
216 // main entry and it also shows up as a separate entry in the bugreport
217 // ZIP file.
218 if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) {
219 MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(),
220 strerror(errno));
221 }
222
Narayan Kamath8f788292017-05-25 13:20:39 +0100223 if (ds.IsZipping() && add_to_zip) {
224 if (!ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd)) {
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100225 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100226 }
227 } else {
228 dump_file_from_fd(type_name, name.c_str(), fd);
229 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100230 }
231
232 return dumped;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700233}
234
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100235static void CloseDumpFds(const std::vector<DumpData>* dumps) {
236 for (auto it = dumps->begin(); it != dumps->end(); ++it) {
237 close(it->fd);
238 }
239}
240
Felipe Leme635ca312016-01-05 14:23:02 -0800241// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700242void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800243 char path[PATH_MAX];
244
245 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
246 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700247 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800248 char linkname[PATH_MAX];
249 ssize_t r = readlink(path, linkname, PATH_MAX);
250 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800251 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800252 return;
253 }
254 linkname[r] = '\0';
255
256 if (mount_points.find(linkname) == mount_points.end()) {
257 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700258 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700259 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
Felipe Leme635ca312016-01-05 14:23:02 -0800260 mount_points.insert(linkname);
261 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800262 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800263 }
264 }
265}
266
267void add_mountinfo() {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700268 if (!ds.IsZipping()) return;
Felipe Leme678727a2016-09-21 17:22:11 -0700269 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800270 mount_points.clear();
Felipe Leme46b85da2016-11-21 17:40:45 -0800271 DurationReporter duration_reporter(title, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700272 for_each_pid(do_mountinfo, nullptr);
273 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800274}
275
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700276static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
277{
278 DIR *d;
279 struct dirent *de;
280 char path[PATH_MAX];
281
282 d = opendir(driverpath);
283 if (d == NULL) {
284 return;
285 }
286
287 while ((de = readdir(d))) {
288 if (de->d_type != DT_LNK) {
289 continue;
290 }
291 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700292 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700293 }
294
295 closedir(d);
296}
297
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700298
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700299
300// dump anrd's trace and add to the zip file.
301// 1. check if anrd is running on this device.
302// 2. send a SIGUSR1 to its pid which will dump anrd's trace.
303// 3. wait until the trace generation completes and add to the zip file.
304static bool dump_anrd_trace() {
305 unsigned int pid;
306 char buf[50], path[PATH_MAX];
307 struct dirent *trace;
308 struct stat st;
309 DIR *trace_dir;
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700310 int retry = 5;
311 long max_ctime = 0, old_mtime;
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700312 long long cur_size = 0;
313 const char *trace_path = "/data/misc/anrd/";
314
Felipe Leme1d486fe2016-10-14 18:06:47 -0700315 if (!ds.IsZipping()) {
316 MYLOGE("Not dumping anrd trace because it's not a zipped bugreport\n");
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700317 return false;
318 }
319
320 // find anrd's pid if it is running.
Ecco Park61ffcf72016-10-27 15:46:26 -0700321 pid = GetPidByName("/system/xbin/anrd");
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700322
323 if (pid > 0) {
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700324 if (stat(trace_path, &st) == 0) {
325 old_mtime = st.st_mtime;
326 } else {
327 MYLOGE("Failed to find: %s\n", trace_path);
328 return false;
329 }
330
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700331 // send SIGUSR1 to the anrd to generate a trace.
332 sprintf(buf, "%u", pid);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700333 if (RunCommand("ANRD_DUMP", {"kill", "-SIGUSR1", buf},
Felipe Leme30dbfa12016-09-02 12:43:26 -0700334 CommandOptions::WithTimeout(1).Build())) {
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700335 MYLOGE("anrd signal timed out. Please manually collect trace\n");
336 return false;
337 }
338
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700339 while (retry-- > 0 && old_mtime == st.st_mtime) {
340 sleep(1);
341 stat(trace_path, &st);
342 }
343
344 if (retry < 0 && old_mtime == st.st_mtime) {
345 MYLOGE("Failed to stat %s or trace creation timeout\n", trace_path);
346 return false;
347 }
348
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700349 // identify the trace file by its creation time.
350 if (!(trace_dir = opendir(trace_path))) {
351 MYLOGE("Can't open trace file under %s\n", trace_path);
352 }
353 while ((trace = readdir(trace_dir))) {
354 if (strcmp(trace->d_name, ".") == 0
355 || strcmp(trace->d_name, "..") == 0) {
356 continue;
357 }
358 sprintf(path, "%s%s", trace_path, trace->d_name);
359 if (stat(path, &st) == 0) {
360 if (st.st_ctime > max_ctime) {
361 max_ctime = st.st_ctime;
362 sprintf(buf, "%s", trace->d_name);
363 }
364 }
365 }
366 closedir(trace_dir);
367
368 // Wait until the dump completes by checking the size of the trace.
369 if (max_ctime > 0) {
370 sprintf(path, "%s%s", trace_path, buf);
371 while(true) {
372 sleep(1);
373 if (stat(path, &st) == 0) {
374 if (st.st_size == cur_size) {
375 break;
376 } else if (st.st_size > cur_size) {
377 cur_size = st.st_size;
378 } else {
379 return false;
380 }
381 } else {
382 MYLOGE("Cant stat() %s anymore\n", path);
383 return false;
384 }
385 }
386 // Add to the zip file.
Felipe Leme1d486fe2016-10-14 18:06:47 -0700387 if (!ds.AddZipEntry("anrd_trace.txt", path)) {
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700388 MYLOGE("Unable to add anrd_trace file %s to zip file\n", path);
389 } else {
390 if (remove(path)) {
391 MYLOGE("Error removing anrd_trace file %s: %s", path, strerror(errno));
392 }
393 return true;
394 }
395 } else {
396 MYLOGE("Can't stats any trace file under %s\n", trace_path);
397 }
398 }
399 return false;
400}
401
Felipe Lemeefd7e272016-05-18 09:27:16 -0700402static void dump_systrace() {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700403 if (!ds.IsZipping()) {
404 MYLOGD("Not dumping systrace because it's not a zipped bugreport\n");
Felipe Leme71a74ac2016-03-17 15:43:25 -0700405 return;
406 }
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700407 std::string systrace_path = ds.GetPath("-systrace.txt");
Felipe Leme14e034a2016-03-30 18:51:03 -0700408 if (systrace_path.empty()) {
409 MYLOGE("Not dumping systrace because path is empty\n");
410 return;
411 }
Felipe Leme71a74ac2016-03-17 15:43:25 -0700412 const char* path = "/sys/kernel/debug/tracing/tracing_on";
413 long int is_tracing;
414 if (read_file_as_long(path, &is_tracing)) {
415 return; // error already logged
416 }
417 if (is_tracing <= 0) {
418 MYLOGD("Skipping systrace because '%s' content is '%ld'\n", path, is_tracing);
419 return;
420 }
421
Felipe Leme14e034a2016-03-30 18:51:03 -0700422 MYLOGD("Running '/system/bin/atrace --async_dump -o %s', which can take several minutes",
423 systrace_path.c_str());
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700424 if (RunCommand("SYSTRACE", {"/system/bin/atrace", "--async_dump", "-o", systrace_path},
Felipe Leme30dbfa12016-09-02 12:43:26 -0700425 CommandOptions::WithTimeout(120).Build())) {
Felipe Leme14e034a2016-03-30 18:51:03 -0700426 MYLOGE("systrace timed out, its zip entry will be incomplete\n");
Felipe Lemec7fe8fe2016-09-21 18:13:20 -0700427 // TODO: RunCommand tries to kill the process, but atrace doesn't die
Felipe Leme30dbfa12016-09-02 12:43:26 -0700428 // peacefully; ideally, we should call strace to stop itself, but there is no such option
429 // yet (just a --async_stop, which stops and dump
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700430 // if (RunCommand("SYSTRACE", {"/system/bin/atrace", "--kill"})) {
Felipe Leme30dbfa12016-09-02 12:43:26 -0700431 // MYLOGE("could not stop systrace ");
432 // }
Felipe Leme14e034a2016-03-30 18:51:03 -0700433 }
Felipe Leme1d486fe2016-10-14 18:06:47 -0700434 if (!ds.AddZipEntry("systrace.txt", systrace_path)) {
Felipe Leme14e034a2016-03-30 18:51:03 -0700435 MYLOGE("Unable to add systrace file %s to zip file\n", systrace_path.c_str());
Felipe Leme71a74ac2016-03-17 15:43:25 -0700436 } else {
Felipe Leme14e034a2016-03-30 18:51:03 -0700437 if (remove(systrace_path.c_str())) {
438 MYLOGE("Error removing systrace file %s: %s", systrace_path.c_str(), strerror(errno));
439 }
Felipe Leme71a74ac2016-03-17 15:43:25 -0700440 }
441}
442
Felipe Lemeefd7e272016-05-18 09:27:16 -0700443static void dump_raft() {
Felipe Lemef0292972016-11-22 13:57:05 -0800444 if (PropertiesHelper::IsUserBuild()) {
Wei Liu341938b2016-04-27 16:18:17 -0700445 return;
446 }
447
Felipe Leme1d486fe2016-10-14 18:06:47 -0700448 std::string raft_path = ds.GetPath("-raft_log.txt");
449 if (raft_path.empty()) {
450 MYLOGD("raft_path is empty\n");
Wei Liu341938b2016-04-27 16:18:17 -0700451 return;
452 }
Wei Liuf0e78d42016-05-25 14:21:02 -0700453
454 struct stat s;
455 if (stat(RAFT_DIR, &s) != 0 || !S_ISDIR(s.st_mode)) {
456 MYLOGD("%s does not exist or is not a directory\n", RAFT_DIR);
457 return;
458 }
459
Felipe Leme30dbfa12016-09-02 12:43:26 -0700460 CommandOptions options = CommandOptions::WithTimeout(600).Build();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700461 if (!ds.IsZipping()) {
462 // Write compressed and encoded raft logs to stdout if it's not a zipped bugreport.
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700463 RunCommand("RAFT LOGS", {"logcompressor", "-r", RAFT_DIR}, options);
Wei Liu341938b2016-04-27 16:18:17 -0700464 return;
465 }
466
Felipe Leme1d486fe2016-10-14 18:06:47 -0700467 RunCommand("RAFT LOGS", {"logcompressor", "-n", "-r", RAFT_DIR, "-o", raft_path}, options);
468 if (!ds.AddZipEntry("raft_log.txt", raft_path)) {
469 MYLOGE("Unable to add raft log %s to zip file\n", raft_path.c_str());
Wei Liu341938b2016-04-27 16:18:17 -0700470 } else {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700471 if (remove(raft_path.c_str())) {
472 MYLOGE("Error removing raft file %s: %s\n", raft_path.c_str(), strerror(errno));
Wei Liu341938b2016-04-27 16:18:17 -0700473 }
474 }
475}
476
Mark Salyzyn326842f2015-04-30 09:49:41 -0700477static bool skip_not_stat(const char *path) {
478 static const char stat[] = "/stat";
479 size_t len = strlen(path);
480 if (path[len - 1] == '/') { /* Directory? */
481 return false;
482 }
483 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
484}
485
Felipe Leme4c2d6632016-09-28 14:32:00 -0700486static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800487 return false;
488}
489
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700490unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700491
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800492//
493// stat offsets
494// Name units description
495// ---- ----- -----------
496// read I/Os requests number of read I/Os processed
497#define __STAT_READ_IOS 0
498// read merges requests number of read I/Os merged with in-queue I/O
499#define __STAT_READ_MERGES 1
500// read sectors sectors number of sectors read
501#define __STAT_READ_SECTORS 2
502// read ticks milliseconds total wait time for read requests
503#define __STAT_READ_TICKS 3
504// write I/Os requests number of write I/Os processed
505#define __STAT_WRITE_IOS 4
506// write merges requests number of write I/Os merged with in-queue I/O
507#define __STAT_WRITE_MERGES 5
508// write sectors sectors number of sectors written
509#define __STAT_WRITE_SECTORS 6
510// write ticks milliseconds total wait time for write requests
511#define __STAT_WRITE_TICKS 7
512// in_flight requests number of I/Os currently in flight
513#define __STAT_IN_FLIGHT 8
514// io_ticks milliseconds total time this block device has been active
515#define __STAT_IO_TICKS 9
516// time_in_queue milliseconds total wait time for all requests
517#define __STAT_IN_QUEUE 10
518#define __STAT_NUMBER_FIELD 11
519//
520// read I/Os, write I/Os
521// =====================
522//
523// These values increment when an I/O request completes.
524//
525// read merges, write merges
526// =========================
527//
528// These values increment when an I/O request is merged with an
529// already-queued I/O request.
530//
531// read sectors, write sectors
532// ===========================
533//
534// These values count the number of sectors read from or written to this
535// block device. The "sectors" in question are the standard UNIX 512-byte
536// sectors, not any device- or filesystem-specific block size. The
537// counters are incremented when the I/O completes.
538#define SECTOR_SIZE 512
539//
540// read ticks, write ticks
541// =======================
542//
543// These values count the number of milliseconds that I/O requests have
544// waited on this block device. If there are multiple I/O requests waiting,
545// these values will increase at a rate greater than 1000/second; for
546// example, if 60 read requests wait for an average of 30 ms, the read_ticks
547// field will increase by 60*30 = 1800.
548//
549// in_flight
550// =========
551//
552// This value counts the number of I/O requests that have been issued to
553// the device driver but have not yet completed. It does not include I/O
554// requests that are in the queue but not yet issued to the device driver.
555//
556// io_ticks
557// ========
558//
559// This value counts the number of milliseconds during which the device has
560// had I/O requests queued.
561//
562// time_in_queue
563// =============
564//
565// This value counts the number of milliseconds that I/O requests have waited
566// on this block device. If there are multiple I/O requests waiting, this
567// value will increase as the product of the number of milliseconds times the
568// number of requests waiting (see "read ticks" above for an example).
569#define S_TO_MS 1000
570//
571
Mark Salyzyn326842f2015-04-30 09:49:41 -0700572static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800573 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700574 bool z;
575 char *cp, *buffer = NULL;
576 size_t i = 0;
577 FILE *fp = fdopen(fd, "rb");
578 getline(&buffer, &i, fp);
579 fclose(fp);
580 if (!buffer) {
581 return -errno;
582 }
583 i = strlen(buffer);
584 while ((i > 0) && (buffer[i - 1] == '\n')) {
585 buffer[--i] = '\0';
586 }
587 if (!*buffer) {
588 free(buffer);
589 return 0;
590 }
591 z = true;
592 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800593 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700594 if (fields[i] != 0) {
595 z = false;
596 }
597 }
598 if (z) { /* never accessed */
599 free(buffer);
600 return 0;
601 }
602
Wei Wang509bb5d2017-06-09 14:42:12 -0700603 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
604 path += sizeof(BLK_DEV_SYS_DIR) - 1;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700605 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700606
607 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
608 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
609 "W-wait", "in-fli", "activ", "T-wait", path, buffer);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700610 free(buffer);
611
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800612 if (fields[__STAT_IO_TICKS]) {
613 unsigned long read_perf = 0;
614 unsigned long read_ios = 0;
615 if (fields[__STAT_READ_TICKS]) {
616 unsigned long long divisor = fields[__STAT_READ_TICKS]
617 * fields[__STAT_IO_TICKS];
618 read_perf = ((unsigned long long)SECTOR_SIZE
619 * fields[__STAT_READ_SECTORS]
620 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
621 / divisor;
622 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
623 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
624 / divisor;
625 }
626
627 unsigned long write_perf = 0;
628 unsigned long write_ios = 0;
629 if (fields[__STAT_WRITE_TICKS]) {
630 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
631 * fields[__STAT_IO_TICKS];
632 write_perf = ((unsigned long long)SECTOR_SIZE
633 * fields[__STAT_WRITE_SECTORS]
634 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
635 / divisor;
636 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
637 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
638 / divisor;
639 }
640
641 unsigned queue = (fields[__STAT_IN_QUEUE]
642 + (fields[__STAT_IO_TICKS] >> 1))
643 / fields[__STAT_IO_TICKS];
644
645 if (!write_perf && !write_ios) {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700646 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 -0800647 } else {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700648 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 -0800649 read_ios, write_perf, write_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800650 }
651
652 /* bugreport timeout factor adjustment */
653 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
654 worst_write_perf = write_perf;
655 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700656 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700657 return 0;
658}
659
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700660/* timeout in ms */
Felipe Leme8620bb42015-11-10 11:04:45 -0800661static unsigned long logcat_timeout(const char *name) {
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -0700662 log_id_t id = android_name_to_log_id(name);
663 unsigned long property_size = __android_logger_get_buffer_size(id);
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700664 /* Engineering margin is ten-fold our guess */
665 return 10 * (property_size + worst_write_perf) / worst_write_perf;
666}
667
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700668void Dumpstate::PrintHeader() const {
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700669 std::string build, fingerprint, radio, bootloader, network;
670 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700671
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700672 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
673 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700674 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
675 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
676 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700677 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
Colin Crossf45fa6b2012-03-26 12:38:26 -0700678
Felipe Lemed8b94e52016-12-08 10:21:44 -0800679 printf("========================================================\n");
680 printf("== dumpstate: %s\n", date);
681 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700682
Felipe Lemed8b94e52016-12-08 10:21:44 -0800683 printf("\n");
684 printf("Build: %s\n", build.c_str());
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700685 // NOTE: fingerprint entry format is important for other tools.
Felipe Lemed8b94e52016-12-08 10:21:44 -0800686 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
687 printf("Bootloader: %s\n", bootloader.c_str());
688 printf("Radio: %s\n", radio.c_str());
689 printf("Network: %s\n", network.c_str());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700690
Felipe Lemed8b94e52016-12-08 10:21:44 -0800691 printf("Kernel: ");
Felipe Lemef0292972016-11-22 13:57:05 -0800692 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
Felipe Lemed8b94e52016-12-08 10:21:44 -0800693 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
pengzhicai24ae8192017-05-25 17:29:33 +0800694 ds.RunCommand("UPTIME", {"uptime"}, CommandOptions::DEFAULT);
Felipe Lemed8b94e52016-12-08 10:21:44 -0800695 printf("Bugreport format version: %s\n", version_.c_str());
696 printf("Dumpstate info: id=%d pid=%d dry_run=%d args=%s extra_options=%s\n", id_, pid_,
697 PropertiesHelper::IsDryRun(), args_.c_str(), extra_options_.c_str());
698 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800699}
700
Felipe Leme24b66ee2016-06-16 10:55:26 -0700701// List of file extensions that can cause a zip file attachment to be rejected by some email
702// service providers.
703static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
704 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
705 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
706 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
707};
708
Felipe Leme1d486fe2016-10-14 18:06:47 -0700709bool Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd) {
710 if (!IsZipping()) {
711 MYLOGD("Not adding zip entry %s from fd because it's not a zipped bugreport\n",
712 entry_name.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800713 return false;
714 }
Felipe Leme24b66ee2016-06-16 10:55:26 -0700715 std::string valid_name = entry_name;
716
717 // Rename extension if necessary.
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -0700718 size_t idx = entry_name.rfind('.');
Felipe Leme24b66ee2016-06-16 10:55:26 -0700719 if (idx != std::string::npos) {
720 std::string extension = entry_name.substr(idx);
721 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
722 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
723 valid_name = entry_name + ".renamed";
724 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
725 }
726 }
727
Felipe Leme6fe9db62016-02-12 09:04:16 -0800728 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
729 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700730 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), ZipWriter::kCompress,
731 get_mtime(fd, ds.now_));
Felipe Leme1d486fe2016-10-14 18:06:47 -0700732 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700733 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700734 ZipWriter::ErrorCodeString(err));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800735 return false;
736 }
737
Felipe Leme770410d2016-01-26 17:07:14 -0800738 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800739 while (1) {
Zach Riggle22200402016-08-18 01:01:24 -0400740 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800741 if (bytes_read == 0) {
742 break;
743 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800744 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800745 return false;
746 }
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700747 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800748 if (err) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700749 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800750 return false;
751 }
752 }
753
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700754 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700755 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700756 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800757 return false;
758 }
759
760 return true;
761}
762
Felipe Leme1d486fe2016-10-14 18:06:47 -0700763bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
764 android::base::unique_fd fd(
765 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700766 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800767 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800768 return false;
769 }
770
Felipe Leme1d486fe2016-10-14 18:06:47 -0700771 return AddZipEntryFromFd(entry_name, fd.get());
Felipe Lemee82a27d2016-01-05 13:35:44 -0800772}
773
774/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700775static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700776 return ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) ? 0 : 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800777}
778
Felipe Leme1d486fe2016-10-14 18:06:47 -0700779void Dumpstate::AddDir(const std::string& dir, bool recursive) {
780 if (!IsZipping()) {
781 MYLOGD("Not adding dir %s because it's not a zipped bugreport\n", dir.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800782 return;
783 }
Felipe Leme678727a2016-09-21 17:22:11 -0700784 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
Felipe Leme46b85da2016-11-21 17:40:45 -0800785 DurationReporter duration_reporter(dir, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700786 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800787}
788
Felipe Leme1d486fe2016-10-14 18:06:47 -0700789bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
790 if (!IsZipping()) {
791 MYLOGD("Not adding text zip entry %s because it's not a zipped bugreport\n",
792 entry_name.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800793 return false;
794 }
Felipe Lemecbce55d2016-02-08 09:53:18 -0800795 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700796 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, ds.now_);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700797 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700798 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700799 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800800 return false;
801 }
802
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700803 err = zip_writer_->WriteBytes(content.c_str(), content.length());
Felipe Leme1d486fe2016-10-14 18:06:47 -0700804 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700805 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700806 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800807 return false;
808 }
809
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700810 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700811 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700812 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800813 return false;
814 }
815
816 return true;
817}
818
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800819static void DoKmsg() {
820 struct stat st;
821 if (!stat(PSTORE_LAST_KMSG, &st)) {
822 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
823 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
824 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
825 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
826 } else {
827 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
828 DumpFile("LAST KMSG", "/proc/last_kmsg");
829 }
830}
831
832static void DoLogcat() {
Vishnu Nair6921f802017-11-22 09:17:23 -0800833 unsigned long timeout_ms;
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800834 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
835 // calculate timeout
Vishnu Nair6921f802017-11-22 09:17:23 -0800836 timeout_ms = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash");
837 if (timeout_ms < 20000) {
838 timeout_ms = 20000;
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800839 }
Tony Makae737652017-03-30 17:47:09 +0100840 RunCommand("SYSTEM LOG",
Vishnu Nair6921f802017-11-22 09:17:23 -0800841 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
842 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
843 timeout_ms = logcat_timeout("events");
844 if (timeout_ms < 20000) {
845 timeout_ms = 20000;
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800846 }
847 RunCommand("EVENT LOG",
Tony Makae737652017-03-30 17:47:09 +0100848 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid",
849 "-d", "*:v"},
Vishnu Nair6921f802017-11-22 09:17:23 -0800850 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
851 timeout_ms = logcat_timeout("radio");
852 if (timeout_ms < 20000) {
853 timeout_ms = 20000;
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800854 }
855 RunCommand("RADIO LOG",
Tony Makae737652017-03-30 17:47:09 +0100856 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid",
857 "-d", "*:v"},
Vishnu Nair6921f802017-11-22 09:17:23 -0800858 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800859
860 RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
861
862 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
863 RunCommand("LAST LOGCAT",
Tony Makae737652017-03-30 17:47:09 +0100864 {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable", "-v", "uid",
865 "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800866}
867
Jayachandran Ca94c7172017-06-10 15:08:12 -0700868static void DumpIpTablesAsRoot() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700869 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
870 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +0900871 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -0700872 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +0900873 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
874 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
875 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
876 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -0700877}
878
Narayan Kamath8f788292017-05-25 13:20:39 +0100879static void AddGlobalAnrTraceFile(const bool add_to_zip, const std::string& anr_traces_file,
880 const std::string& anr_traces_dir) {
Felipe Lemee184f662016-10-27 10:04:47 -0700881 std::string dump_traces_dir;
882
Felipe Lemee184f662016-10-27 10:04:47 -0700883 if (dump_traces_path != nullptr) {
884 if (add_to_zip) {
885 dump_traces_dir = dirname(dump_traces_path);
886 MYLOGD("Adding ANR traces (directory %s) to the zip file\n", dump_traces_dir.c_str());
887 ds.AddDir(dump_traces_dir, true);
888 } else {
889 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
890 dump_traces_path);
891 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
892 }
893 }
894
Felipe Lemee184f662016-10-27 10:04:47 -0700895
896 // Make sure directory is not added twice.
897 // TODO: this is an overzealous check because it's relying on dump_traces_path - which is
898 // generated by dump_traces() - and anr_traces_path - which is retrieved from a system
899 // property - but in reality they're the same path (although the former could be nullptr).
900 // Anyways, once dump_traces() is refactored as a private Dumpstate function, this logic should
901 // be revisited.
902 bool already_dumped = anr_traces_dir == dump_traces_dir;
903
Narayan Kamath8f788292017-05-25 13:20:39 +0100904 MYLOGD("AddGlobalAnrTraceFile(): dump_traces_dir=%s, anr_traces_dir=%s, already_dumped=%d\n",
Felipe Lemee184f662016-10-27 10:04:47 -0700905 dump_traces_dir.c_str(), anr_traces_dir.c_str(), already_dumped);
906
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100907 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
908 open(anr_traces_file.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
909 if (fd.get() < 0) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100910 printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_file.c_str(), strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -0700911 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +0100912 if (add_to_zip) {
913 if (!already_dumped) {
914 MYLOGD("Adding dalvik ANR traces (directory %s) to the zip file\n",
915 anr_traces_dir.c_str());
916 ds.AddDir(anr_traces_dir, true);
Felipe Lemee184f662016-10-27 10:04:47 -0700917 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100918 } else {
919 MYLOGD("Dumping last ANR traces (%s) to the main bugreport entry\n",
920 anr_traces_file.c_str());
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100921 dump_file_from_fd("VM TRACES AT LAST ANR", anr_traces_file.c_str(), fd.get());
Narayan Kamath8f788292017-05-25 13:20:39 +0100922 }
923 }
924}
925
926static void AddAnrTraceDir(const bool add_to_zip, const std::string& anr_traces_dir) {
927 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
928 anr_traces_dir.c_str());
929
930 // If we're here, dump_traces_path will always be a temporary file
931 // (created with mkostemp or similar) that contains dumps taken earlier
932 // on in the process.
933 if (dump_traces_path != nullptr) {
934 if (add_to_zip) {
935 ds.AddZipEntry(ZIP_ROOT_DIR + anr_traces_dir + "/traces-just-now.txt", dump_traces_path);
936 } else {
937 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
938 dump_traces_path);
939 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
940 }
941
942 const int ret = unlink(dump_traces_path);
943 if (ret == -1) {
944 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
945 strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -0700946 }
947 }
948
Narayan Kamathbd863722017-06-01 18:50:12 +0100949 // Add a specific message for the first ANR Dump.
950 if (anr_data->size() > 0) {
951 AddDumps(anr_data->begin(), anr_data->begin() + 1,
952 "VM TRACES AT LAST ANR", add_to_zip);
953
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100954 // The "last" ANR will always be included as separate entry in the zip file. In addition,
955 // it will be present in the body of the main entry if |add_to_zip| == false.
956 //
957 // Historical ANRs are always included as separate entries in the bugreport zip file.
958 AddDumps(anr_data->begin() + ((add_to_zip) ? 1 : 0), anr_data->end(),
959 "HISTORICAL ANR", true /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +0100960 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +0100961 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
962 }
963}
964
965static void AddAnrTraceFiles() {
966 const bool add_to_zip = ds.IsZipping() && ds.version_ == VERSION_SPLIT_ANR;
967
968 std::string anr_traces_file;
969 std::string anr_traces_dir;
970 bool is_global_trace_file = true;
971
972 // First check whether the stack-trace-dir property is set. When it's set,
973 // each ANR trace will be written to a separate file and not to a global
974 // stack trace file.
975 anr_traces_dir = android::base::GetProperty("dalvik.vm.stack-trace-dir", "");
976 if (anr_traces_dir.empty()) {
977 anr_traces_file = android::base::GetProperty("dalvik.vm.stack-trace-file", "");
978 if (!anr_traces_file.empty()) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100979 anr_traces_dir = dirname(anr_traces_file.c_str());
980 }
Narayan Kamathbd863722017-06-01 18:50:12 +0100981 } else {
982 is_global_trace_file = false;
Narayan Kamath8f788292017-05-25 13:20:39 +0100983 }
984
985 // We have neither configured a global trace file nor a trace directory,
986 // there will be nothing to dump.
987 if (anr_traces_file.empty() && anr_traces_dir.empty()) {
988 printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
Felipe Lemee184f662016-10-27 10:04:47 -0700989 return;
990 }
991
Narayan Kamath8f788292017-05-25 13:20:39 +0100992 if (is_global_trace_file) {
993 AddGlobalAnrTraceFile(add_to_zip, anr_traces_file, anr_traces_dir);
994 } else {
995 AddAnrTraceDir(add_to_zip, anr_traces_dir);
996 }
997
Felipe Lemee184f662016-10-27 10:04:47 -0700998 /* slow traces for slow operations */
999 struct stat st;
Narayan Kamath8f788292017-05-25 13:20:39 +01001000 if (!anr_traces_dir.empty()) {
Felipe Lemee184f662016-10-27 10:04:47 -07001001 int i = 0;
Narayan Kamath8f788292017-05-25 13:20:39 +01001002 while (true) {
1003 const std::string slow_trace_path =
1004 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
1005 if (stat(slow_trace_path.c_str(), &st)) {
Felipe Lemee184f662016-10-27 10:04:47 -07001006 // No traces file at this index, done with the files.
1007 break;
1008 }
Narayan Kamath8f788292017-05-25 13:20:39 +01001009 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
Felipe Lemee184f662016-10-27 10:04:47 -07001010 i++;
1011 }
1012 }
1013}
1014
Wei Wang509bb5d2017-06-09 14:42:12 -07001015static void DumpBlockStatFiles() {
1016 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -07001017
Wei Wang1dc1ef52017-06-12 11:28:37 -07001018 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
1019
1020 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001021 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1022 return;
1023 }
1024
1025 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -07001026 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001027 if ((d->d_name[0] == '.')
1028 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1029 || (d->d_name[1] == '\0'))) {
1030 continue;
1031 }
1032 const std::string new_path =
1033 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1034 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1035 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1036 printf("\n");
1037 }
Wei Wang1dc1ef52017-06-12 11:28:37 -07001038 return;
Wei Wang509bb5d2017-06-09 14:42:12 -07001039}
Jayachandran Ca94c7172017-06-10 15:08:12 -07001040
1041static void DumpPacketStats() {
1042 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
1043 DumpFile("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
1044 DumpFile("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
1045 DumpFile("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
1046 DumpFile("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
1047}
1048
1049static void DumpIpAddrAndRules() {
1050 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
1051 RunCommand("NETWORK INTERFACES", {"ip", "link"});
1052 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1053 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1054 RunCommand("IP RULES", {"ip", "rule", "show"});
1055 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1056}
1057
Vishnu Nair780b1282017-10-10 13:57:24 -07001058// Runs dumpsys on services that must dump first and and will take less than 100ms to dump.
1059static void RunDumpsysCritical() {
1060 if (ds.CurrentVersionSupportsPriorityDumps()) {
1061 RunDumpsys("DUMPSYS CRITICAL", {"--priority", "CRITICAL"},
1062 CommandOptions::WithTimeout(5).DropRoot().Build());
1063 } else {
1064 RunDumpsys("DUMPSYS MEMINFO", {"meminfo", "-a"},
1065 CommandOptions::WithTimeout(90).DropRoot().Build());
1066 RunDumpsys("DUMPSYS CPUINFO", {"cpuinfo", "-a"},
1067 CommandOptions::WithTimeout(10).DropRoot().Build());
1068 }
1069}
1070
1071// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
1072static void RunDumpsysHigh() {
1073 if (ds.CurrentVersionSupportsPriorityDumps()) {
1074 RunDumpsys("DUMPSYS HIGH", {"--priority", "HIGH"},
1075 CommandOptions::WithTimeout(20).DropRoot().Build());
1076 } else {
1077 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"});
1078 }
1079}
1080
1081// Runs dumpsys on services that must dump but can take up to 10s to dump.
1082static void RunDumpsysNormal() {
1083 if (ds.CurrentVersionSupportsPriorityDumps()) {
1084 RunDumpsys("DUMPSYS NORMAL", {"--priority", "NORMAL"},
1085 CommandOptions::WithTimeout(90).DropRoot().Build());
1086 } else {
1087 RunDumpsys("DUMPSYS", {"--skip", "meminfo", "cpuinfo"},
Vishnu Nair652cc802017-11-30 15:18:30 -08001088 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Vishnu Nair780b1282017-10-10 13:57:24 -07001089 }
1090}
1091
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001092static void dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001093 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001094
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001095 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
pengzhicai24ae8192017-05-25 17:29:33 +08001096 /* TODO: Remove duplicate uptime call when tools use it from header */
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001097 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001098 DumpBlockStatFiles();
Mark Salyzyn8c8130e2015-12-09 11:21:28 -08001099 dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001100 DumpFile("MEMORY INFO", "/proc/meminfo");
1101 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001102 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Felipe Lemef0292972016-11-22 13:57:05 -08001103 RunCommand("PROCRANK", {"procrank"}, AS_ROOT_20);
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001104 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1105 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1106 DumpFile("SLAB INFO", "/proc/slabinfo");
1107 DumpFile("ZONEINFO", "/proc/zoneinfo");
1108 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1109 DumpFile("BUDDYINFO", "/proc/buddyinfo");
1110 DumpFile("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001111
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001112 DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources");
1113 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
1114 DumpFile("KERNEL SYNC", "/d/sync");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001115
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001116 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001117 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Felipe Lemef0292972016-11-22 13:57:05 -08001118 RunCommand("LIBRANK", {"librank"}, CommandOptions::AS_ROOT);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001119
Andreas Huber69ec3ac2017-03-23 09:47:51 -07001120 if (ds.IsZipping()) {
1121 RunCommand(
1122 "HARDWARE HALS",
1123 {"lshal", std::string("--debug=") + kLsHalDebugPath},
Yifan Hong48e83a12017-10-03 14:10:07 -07001124 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
Andreas Huber69ec3ac2017-03-23 09:47:51 -07001125
1126 ds.AddZipEntry("lshal-debug.txt", kLsHalDebugPath);
1127
1128 unlink(kLsHalDebugPath.c_str());
1129 } else {
1130 RunCommand(
Yifan Hong48e83a12017-10-03 14:10:07 -07001131 "HARDWARE HALS", {"lshal", "--debug"},
1132 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
Andreas Huber69ec3ac2017-03-23 09:47:51 -07001133 }
Steven Moreland81b429e2017-01-31 19:50:46 -08001134
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001135 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001136 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001137 struct stat s;
1138 if (stat("/proc/modules", &s) != 0) {
1139 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1140 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001141 RunCommand("LSMOD", {"lsmod"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001142 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001143
Colin Crossf45fa6b2012-03-26 12:38:26 -07001144 do_dmesg();
1145
Felipe Lemef0292972016-11-22 13:57:05 -08001146 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Jeff Brown1dc94e32014-09-11 14:15:27 -07001147 for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES");
1148 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001149 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001150
Ajay Panicker2ff8e872017-04-27 14:04:32 -07001151 /* Dump Bluetooth HCI logs */
1152 ds.AddDir("/data/misc/bluetooth/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001153
Felipe Leme9a523ae2016-10-20 15:10:33 -07001154 if (!ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001155 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001156 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001157 }
1158
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001159 DoLogcat();
Mark Salyzynecc07632015-07-30 14:57:09 -07001160
Felipe Lemee184f662016-10-27 10:04:47 -07001161 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001162
Narayan Kamath8f788292017-05-25 13:20:39 +01001163 // NOTE: tombstones are always added as separate entries in the zip archive
1164 // and are not interspersed with the main report.
Narayan Kamathbd863722017-06-01 18:50:12 +01001165 const bool tombstones_dumped = AddDumps(tombstone_data->begin(), tombstone_data->end(),
1166 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001167 if (!tombstones_dumped) {
1168 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001169 }
1170
Jayachandran Ca94c7172017-06-10 15:08:12 -07001171 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001172
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001173 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001174
Jayachandran Ca94c7172017-06-10 15:08:12 -07001175 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001176
1177 dump_route_tables();
1178
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001179 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1180 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1181 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001182
Vishnu Nair780b1282017-10-10 13:57:24 -07001183 RunDumpsysHigh();
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001184
Elliott Hughes23ccc622017-02-28 10:14:22 -08001185 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001186
Jin Qianf334d662017-10-10 14:41:37 -07001187 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001188
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001189 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001190
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001191 RunCommand("LAST RADIO LOG", {"parse_radio_log", "/proc/last_radio_log"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001192
Felipe Lemed8b94e52016-12-08 10:21:44 -08001193 printf("------ BACKLIGHTS ------\n");
1194 printf("LCD brightness=");
Felipe Leme678727a2016-09-21 17:22:11 -07001195 DumpFile("", "/sys/class/leds/lcd-backlight/brightness");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001196 printf("Button brightness=");
Felipe Leme678727a2016-09-21 17:22:11 -07001197 DumpFile("", "/sys/class/leds/button-backlight/brightness");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001198 printf("Keyboard brightness=");
Felipe Leme678727a2016-09-21 17:22:11 -07001199 DumpFile("", "/sys/class/leds/keyboard-backlight/brightness");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001200 printf("ALS mode=");
Felipe Leme678727a2016-09-21 17:22:11 -07001201 DumpFile("", "/sys/class/leds/lcd-backlight/als");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001202 printf("LCD driver registers:\n");
Felipe Leme678727a2016-09-21 17:22:11 -07001203 DumpFile("", "/sys/class/leds/lcd-backlight/registers");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001204 printf("\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001205
1206 /* Binder state is expensive to look at as it uses a lot of memory. */
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001207 DumpFile("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
1208 DumpFile("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
1209 DumpFile("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
1210 DumpFile("BINDER STATS", "/sys/kernel/debug/binder/stats");
1211 DumpFile("BINDER STATE", "/sys/kernel/debug/binder/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001212
Vishnu Nair36b4cdb2017-11-17 10:27:05 -08001213 /* Add window and surface trace files. */
1214 if (!PropertiesHelper::IsUserBuild()) {
1215 ds.AddDir(WMTRACE_DATA_DIR, false);
1216 }
1217
Felipe Leme6f674ae2016-11-18 17:10:33 -08001218 ds.DumpstateBoard();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001219
Steven Moreland7440ddb2016-12-15 16:13:39 -08001220 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001221 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1222 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001223 // su does not exist on user builds, so try running without it.
1224 // This way any implementations of vril-dump that do not require
1225 // root can run on user builds.
1226 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001227 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001228 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001229 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001230 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001231 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001232 }
1233
Felipe Lemed8b94e52016-12-08 10:21:44 -08001234 printf("========================================================\n");
1235 printf("== Android Framework Services\n");
1236 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001237
Vishnu Nair780b1282017-10-10 13:57:24 -07001238 RunDumpsysNormal();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001239
Felipe Lemed8b94e52016-12-08 10:21:44 -08001240 printf("========================================================\n");
1241 printf("== Checkins\n");
1242 printf("========================================================\n");
Dianne Hackborn02bea972013-06-26 18:59:09 -07001243
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001244 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1245 RunDumpsys("CHECKIN MEMINFO", {"meminfo", "--checkin"});
1246 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"});
1247 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"});
1248 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"});
1249 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"});
Dianne Hackborn02bea972013-06-26 18:59:09 -07001250
Felipe Lemed8b94e52016-12-08 10:21:44 -08001251 printf("========================================================\n");
1252 printf("== Running Application Activities\n");
1253 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001254
Winson Chung1434a5c2017-02-28 17:09:24 -08001255 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001256
Felipe Lemed8b94e52016-12-08 10:21:44 -08001257 printf("========================================================\n");
1258 printf("== Running Application Services\n");
1259 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001260
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001261 RunDumpsys("APP SERVICES", {"activity", "service", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001262
Felipe Lemed8b94e52016-12-08 10:21:44 -08001263 printf("========================================================\n");
1264 printf("== Running Application Providers\n");
1265 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001266
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001267 RunDumpsys("APP PROVIDERS", {"activity", "provider", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001268
Adrian Roos8b397ab2017-04-04 16:35:44 -07001269 printf("========================================================\n");
1270 printf("== Dropbox crashes\n");
1271 printf("========================================================\n");
1272
1273 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1274 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1275
Felipe Lemed8b94e52016-12-08 10:21:44 -08001276 printf("========================================================\n");
1277 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1278 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1279 printf("========================================================\n");
1280 printf("== dumpstate: done (id %d)\n", ds.id_);
1281 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001282}
1283
Jayachandran Ca94c7172017-06-10 15:08:12 -07001284// This method collects dumpsys for telephony debugging only
1285static void DumpstateTelephonyOnly() {
1286 DurationReporter duration_reporter("DUMPSTATE");
1287
1288 DumpIpTablesAsRoot();
1289
1290 if (!DropRootUser()) {
1291 return;
1292 }
1293
1294 do_dmesg();
1295 DoLogcat();
1296 DumpPacketStats();
1297 DoKmsg();
1298 DumpIpAddrAndRules();
1299 dump_route_tables();
1300
1301 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
1302 CommandOptions::WithTimeout(10).Build());
1303
1304 RunCommand("SYSTEM PROPERTIES", {"getprop"});
1305
1306 printf("========================================================\n");
1307 printf("== Android Framework Services\n");
1308 printf("========================================================\n");
1309
Vishnu Nair652cc802017-11-30 15:18:30 -08001310 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1311 SEC_TO_MSEC(10));
1312 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
1313 SEC_TO_MSEC(10));
Jayachandran Ca94c7172017-06-10 15:08:12 -07001314
1315 printf("========================================================\n");
1316 printf("== Running Application Services\n");
1317 printf("========================================================\n");
1318
1319 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
1320
1321 printf("========================================================\n");
1322 printf("== dumpstate: done (id %d)\n", ds.id_);
1323 printf("========================================================\n");
1324}
1325
Felipe Leme6f674ae2016-11-18 17:10:33 -08001326void Dumpstate::DumpstateBoard() {
1327 DurationReporter duration_reporter("dumpstate_board()");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001328 printf("========================================================\n");
1329 printf("== Board\n");
1330 printf("========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001331
Chris Phoenix69d92212017-01-24 23:01:13 -08001332 ::android::sp<IDumpstateDevice> dumpstate_device(IDumpstateDevice::getService());
Felipe Leme6f674ae2016-11-18 17:10:33 -08001333 if (dumpstate_device == nullptr) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08001334 MYLOGE("No IDumpstateDevice implementation\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001335 return;
1336 }
1337
1338 if (!IsZipping()) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08001339 MYLOGD("Not dumping board info because it's not a zipped bugreport\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001340 return;
1341 }
1342
Jie Song9fbfad02017-06-20 16:29:42 -07001343 std::string path[NUM_OF_DUMPS];
1344 android::base::unique_fd fd[NUM_OF_DUMPS];
1345 int numFds = 0;
Felipe Leme6f674ae2016-11-18 17:10:33 -08001346
Jie Song9fbfad02017-06-20 16:29:42 -07001347 for (int i = 0; i < NUM_OF_DUMPS; i++) {
1348 path[i] = kDumpstateBoardPath + kDumpstateBoardFiles[i];
1349 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", path[i].c_str());
1350
1351 fd[i] = android::base::unique_fd(
1352 TEMP_FAILURE_RETRY(open(path[i].c_str(),
1353 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1354 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1355 if (fd[i] < 0) {
1356 MYLOGE("Could not open file %s: %s\n", path[i].c_str(), strerror(errno));
1357 return;
1358 } else {
1359 numFds++;
1360 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001361 }
1362
Jie Song9fbfad02017-06-20 16:29:42 -07001363 native_handle_t *handle = native_handle_create(numFds, 0);
Felipe Leme6f674ae2016-11-18 17:10:33 -08001364 if (handle == nullptr) {
1365 MYLOGE("Could not create native_handle\n");
1366 return;
1367 }
Jie Song9fbfad02017-06-20 16:29:42 -07001368
1369 for (int i = 0; i < numFds; i++) {
1370 handle->data[i] = fd[i].release();
1371 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001372
Felipe Lemef0292972016-11-22 13:57:05 -08001373 // TODO: need a timeout mechanism so dumpstate does not hang on device implementation call.
Steven Moreland7440ddb2016-12-15 16:13:39 -08001374 android::hardware::Return<void> status = dumpstate_device->dumpstateBoard(handle);
1375 if (!status.isOk()) {
1376 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
1377 native_handle_close(handle);
1378 native_handle_delete(handle);
1379 return;
1380 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001381
Jie Song9fbfad02017-06-20 16:29:42 -07001382 for (int i = 0; i < numFds; i++) {
1383 struct stat s;
1384 if (fstat(handle->data[i], &s) == -1) {
1385 MYLOGE("Failed to fstat %s: %d\n", kDumpstateBoardFiles[i].c_str(), errno);
1386 } else if (s.st_size > 0) {
1387 AddZipEntry(kDumpstateBoardFiles[i], path[i]);
1388 } else {
1389 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
1390 }
1391 }
1392
Felipe Lemed8b94e52016-12-08 10:21:44 -08001393 printf("*** See dumpstate-board.txt entry ***\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001394
1395 native_handle_close(handle);
1396 native_handle_delete(handle);
1397
Jie Song9fbfad02017-06-20 16:29:42 -07001398 for (int i = 0; i < numFds; i++) {
1399 if (remove(path[i].c_str()) != 0) {
1400 MYLOGE("Could not remove(%s): %s\n", path[i].c_str(), strerror(errno));
1401 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001402 }
1403}
1404
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001405static void ShowUsageAndExit(int exitCode = 1) {
1406 fprintf(stderr,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001407 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file] [-d] [-p] "
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001408 "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
1409 " -h: display this help message\n"
1410 " -b: play sound file instead of vibrate, at beginning of job\n"
1411 " -e: play sound file instead of vibrate, at end of job\n"
1412 " -o: write to file (instead of stdout)\n"
1413 " -d: append date to filename (requires -o)\n"
1414 " -p: capture screenshot to filename.png (requires -o)\n"
1415 " -z: generate zipped file (requires -o)\n"
1416 " -s: write output to control socket (for init)\n"
1417 " -S: write file location to control socket (for init; requires -o and -z)"
1418 " -q: disable vibrate\n"
1419 " -B: send broadcast when finished (requires -o)\n"
1420 " -P: send broadcast when started and update system properties on "
1421 "progress (requires -o and -B)\n"
1422 " -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
1423 "shouldn't be used with -P)\n"
Felipe Lemed071c682016-10-20 16:48:00 -07001424 " -v: prints the dumpstate header and exit\n");
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001425 exit(exitCode);
1426}
1427
1428static void ExitOnInvalidArgs() {
1429 fprintf(stderr, "invalid combination of args\n");
1430 ShowUsageAndExit();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001431}
1432
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08001433static void sig_handler(int) {
Andres Morales2e671bb2014-08-21 12:38:22 -07001434 _exit(EXIT_FAILURE);
John Michelau885f8882013-05-06 16:42:02 -05001435}
1436
Wei Liuf87959e2016-08-26 14:51:42 -07001437static void register_sig_handler() {
1438 struct sigaction sa;
1439 sigemptyset(&sa.sa_mask);
1440 sa.sa_flags = 0;
1441 sa.sa_handler = sig_handler;
1442 sigaction(SIGPIPE, &sa, NULL); // broken pipe
1443 sigaction(SIGSEGV, &sa, NULL); // segment fault
1444 sigaction(SIGINT, &sa, NULL); // ctrl-c
1445 sigaction(SIGTERM, &sa, NULL); // killed
1446 sigaction(SIGQUIT, &sa, NULL); // quit
1447}
1448
Felipe Leme1d486fe2016-10-14 18:06:47 -07001449bool Dumpstate::FinishZipFile() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001450 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07001451 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07001452 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001453 // Final timestamp
1454 char date[80];
1455 time_t the_real_now_please_stand_up = time(nullptr);
1456 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07001457 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001458 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001459
Felipe Leme9a523ae2016-10-20 15:10:33 -07001460 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001461 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08001462 return false;
1463 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07001464 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001465 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08001466 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08001467 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08001468
Felipe Leme0f3fb202016-06-10 17:10:53 -07001469 // Add log file (which contains stderr output) to zip...
1470 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001471 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07001472 MYLOGE("Failed to add dumpstate log to .zip file\n");
1473 return false;
1474 }
1475 // ... and re-opens it for further logging.
Felipe Leme9a523ae2016-10-20 15:10:33 -07001476 redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()));
Felipe Leme0f3fb202016-06-10 17:10:53 -07001477 fprintf(stderr, "\n");
1478
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001479 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07001480 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001481 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001482 return false;
1483 }
1484
Felipe Leme1d486fe2016-10-14 18:06:47 -07001485 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
1486 ds.zip_file.reset(nullptr);
1487
Felipe Lemee9d2c542016-11-15 11:48:26 -08001488 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
1489 if (remove(tmp_path_.c_str()) != 0) {
1490 MYLOGE("Failed to remove temporary file (%s): %s\n", tmp_path_.c_str(), strerror(errno));
Felipe Lemec4eee562016-04-21 15:42:55 -07001491 }
1492
Felipe Leme1e9edc62015-12-21 16:02:13 -08001493 return true;
1494}
Felipe Leme6e01fa62015-11-11 19:35:14 -08001495
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -07001496static std::string SHA256_file_hash(const std::string& filepath) {
Andreas Gampe27cd7b22016-07-18 18:24:05 -07001497 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK
1498 | O_CLOEXEC | O_NOFOLLOW)));
Andreas Gampeaff68432016-07-18 18:01:27 -07001499 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001500 MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
Michal Karpinski4db754f2015-12-11 18:04:32 +00001501 return NULL;
1502 }
1503
1504 SHA256_CTX ctx;
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001505 SHA256_Init(&ctx);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001506
1507 std::vector<uint8_t> buffer(65536);
1508 while (1) {
1509 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
1510 if (bytes_read == 0) {
1511 break;
1512 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001513 MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
Michal Karpinski4db754f2015-12-11 18:04:32 +00001514 return NULL;
1515 }
1516
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001517 SHA256_Update(&ctx, buffer.data(), bytes_read);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001518 }
1519
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001520 uint8_t hash[SHA256_DIGEST_LENGTH];
1521 SHA256_Final(hash, &ctx);
1522
1523 char hash_buffer[SHA256_DIGEST_LENGTH * 2 + 1];
1524 for(size_t i = 0; i < SHA256_DIGEST_LENGTH; i++) {
Michal Karpinskicbbdf732016-01-07 20:45:02 +00001525 sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001526 }
1527 hash_buffer[sizeof(hash_buffer) - 1] = 0;
1528 return std::string(hash_buffer);
1529}
1530
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001531static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) {
1532 // clang-format off
1533 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0",
1534 "--receiver-foreground", "--receiver-include-background", "-a", action};
1535 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08001536
1537 am.insert(am.end(), args.begin(), args.end());
1538
Felipe Leme8d2410e2017-02-08 09:46:08 -08001539 RunCommand("", am,
1540 CommandOptions::WithTimeout(20)
1541 .Log("Sending broadcast: '%s'\n")
1542 .Always()
1543 .DropRoot()
1544 .RedirectStderr()
1545 .Build());
1546}
1547
Felipe Leme35b8cf12017-02-10 15:47:29 -08001548static void Vibrate(int duration_ms) {
1549 // clang-format off
1550 RunCommand("", {"cmd", "vibrator", "vibrate", std::to_string(duration_ms), "dumpstate"},
1551 CommandOptions::WithTimeout(10)
1552 .Log("Vibrate: '%s'\n")
1553 .Always()
1554 .Build());
1555 // clang-format on
1556}
1557
Colin Crossf45fa6b2012-03-26 12:38:26 -07001558int main(int argc, char *argv[]) {
1559 int do_add_date = 0;
Felipe Leme6e01fa62015-11-11 19:35:14 -08001560 int do_zip_file = 0;
John Michelau1f794c42012-09-17 11:20:19 -05001561 int do_vibrate = 1;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001562 char* use_outfile = 0;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001563 int use_socket = 0;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001564 int use_control_socket = 0;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001565 int do_fb = 0;
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07001566 int do_broadcast = 0;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001567 int is_remote_mode = 0;
Felipe Lemed071c682016-10-20 16:48:00 -07001568 bool show_header_only = false;
Felipe Leme75876a22016-10-27 16:31:27 -07001569 bool do_start_service = false;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001570 bool telephony_only = false;
Felipe Leme8fecfdd2016-02-09 10:40:07 -08001571
Colin Crossf45fa6b2012-03-26 12:38:26 -07001572 /* set as high priority, and protect from OOM killer */
1573 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001574
Felipe Lemed071c682016-10-20 16:48:00 -07001575 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001576 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001577 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001578 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001579 } else {
1580 /* fallback to kernels <= 2.6.35 */
1581 oom_adj = fopen("/proc/self/oom_adj", "we");
1582 if (oom_adj) {
1583 fputs("-17", oom_adj);
1584 fclose(oom_adj);
1585 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001586 }
1587
Jeff Brown1dc94e32014-09-11 14:15:27 -07001588 /* parse arguments */
Colin Crossf45fa6b2012-03-26 12:38:26 -07001589 int c;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001590 while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
Colin Crossf45fa6b2012-03-26 12:38:26 -07001591 switch (c) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001592 // clang-format off
Felipe Lemed071c682016-10-20 16:48:00 -07001593 case 'd': do_add_date = 1; break;
1594 case 'z': do_zip_file = 1; break;
1595 case 'o': use_outfile = optarg; break;
1596 case 's': use_socket = 1; break;
1597 case 'S': use_control_socket = 1; break;
1598 case 'v': show_header_only = true; break;
1599 case 'q': do_vibrate = 0; break;
1600 case 'p': do_fb = 1; break;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001601 case 'P': ds.update_progress_ = true; break;
Felipe Lemed071c682016-10-20 16:48:00 -07001602 case 'R': is_remote_mode = 1; break;
1603 case 'B': do_broadcast = 1; break;
1604 case 'V': break; // compatibility no-op
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001605 case 'h':
1606 ShowUsageAndExit(0);
1607 break;
1608 default:
1609 fprintf(stderr, "Invalid option: %c\n", c);
1610 ShowUsageAndExit();
Felipe Lemee844a9d2016-09-21 15:01:39 -07001611 // clang-format on
Colin Crossf45fa6b2012-03-26 12:38:26 -07001612 }
1613 }
1614
Felipe Lemed071c682016-10-20 16:48:00 -07001615 // TODO: use helper function to convert argv into a string
1616 for (int i = 0; i < argc; i++) {
1617 ds.args_ += argv[i];
1618 if (i < argc - 1) {
1619 ds.args_ += " ";
1620 }
1621 }
1622
1623 ds.extra_options_ = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001624 if (!ds.extra_options_.empty()) {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001625 // Framework uses a system property to override some command-line args.
1626 // Currently, it contains the type of the requested bugreport.
Felipe Leme9a523ae2016-10-20 15:10:33 -07001627 if (ds.extra_options_ == "bugreportplus") {
Felipe Leme75876a22016-10-27 16:31:27 -07001628 // Currently, the dumpstate binder is only used by Shell to update progress.
1629 do_start_service = true;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001630 ds.update_progress_ = true;
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001631 do_fb = 0;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001632 } else if (ds.extra_options_ == "bugreportremote") {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001633 do_vibrate = 0;
1634 is_remote_mode = 1;
1635 do_fb = 0;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001636 } else if (ds.extra_options_ == "bugreportwear") {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001637 ds.update_progress_ = true;
Alain Vongsouvanh46edde32017-10-25 16:16:24 -07001638 do_zip_file = 1;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001639 } else if (ds.extra_options_ == "bugreporttelephony") {
1640 telephony_only = true;
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001641 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001642 MYLOGE("Unknown extra option: %s\n", ds.extra_options_.c_str());
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001643 }
1644 // Reset the property
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001645 android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, "");
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001646 }
1647
Naveen Kallab53a1c92017-03-16 18:17:25 -07001648 ds.notification_title = android::base::GetProperty(PROPERTY_EXTRA_TITLE, "");
1649 if (!ds.notification_title.empty()) {
1650 // Reset the property
1651 android::base::SetProperty(PROPERTY_EXTRA_TITLE, "");
1652
1653 ds.notification_description = android::base::GetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
1654 if (!ds.notification_description.empty()) {
1655 // Reset the property
1656 android::base::SetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
1657 }
1658 MYLOGD("notification (title: %s, description: %s)\n",
1659 ds.notification_title.c_str(), ds.notification_description.c_str());
1660 }
1661
Felipe Leme9a523ae2016-10-20 15:10:33 -07001662 if ((do_zip_file || do_add_date || ds.update_progress_ || do_broadcast) && !use_outfile) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001663 ExitOnInvalidArgs();
Felipe Leme6e01fa62015-11-11 19:35:14 -08001664 }
1665
Felipe Leme2628e9e2016-04-12 16:36:51 -07001666 if (use_control_socket && !do_zip_file) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001667 ExitOnInvalidArgs();
Felipe Leme2628e9e2016-04-12 16:36:51 -07001668 }
1669
Felipe Leme9a523ae2016-10-20 15:10:33 -07001670 if (ds.update_progress_ && !do_broadcast) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001671 ExitOnInvalidArgs();
Felipe Leme71bbfc52015-11-23 14:14:51 -08001672 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001673
Felipe Leme9a523ae2016-10-20 15:10:33 -07001674 if (is_remote_mode && (ds.update_progress_ || !do_broadcast || !do_zip_file || !do_add_date)) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001675 ExitOnInvalidArgs();
Michal Karpinski4db754f2015-12-11 18:04:32 +00001676 }
1677
Felipe Lemed071c682016-10-20 16:48:00 -07001678 if (ds.version_ == VERSION_DEFAULT) {
1679 ds.version_ = VERSION_CURRENT;
Felipe Leme809d74e2016-02-02 12:57:00 -08001680 }
1681
Vishnu Nair780b1282017-10-10 13:57:24 -07001682 if (ds.version_ != VERSION_CURRENT && ds.version_ != VERSION_SPLIT_ANR &&
1683 ds.version_ != VERSION_PRIORITY_DUMPS) {
1684 MYLOGE(
1685 "invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s', '%s')\n",
1686 ds.version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
1687 VERSION_SPLIT_ANR.c_str(), VERSION_PRIORITY_DUMPS.c_str());
Felipe Lemed071c682016-10-20 16:48:00 -07001688 exit(1);
1689 }
1690
1691 if (show_header_only) {
1692 ds.PrintHeader();
1693 exit(0);
1694 }
1695
Felipe Leme7447d7c2016-11-03 18:12:22 -07001696 /* redirect output if needed */
1697 bool is_redirecting = !use_socket && use_outfile;
1698
1699 // TODO: temporarily set progress until it's part of the Dumpstate constructor
1700 std::string stats_path =
1701 is_redirecting ? android::base::StringPrintf("%s/dumpstate-stats.txt", dirname(use_outfile))
1702 : "";
1703 ds.progress_.reset(new Progress(stats_path));
1704
Felipe Lemed071c682016-10-20 16:48:00 -07001705 /* gets the sequential id */
Felipe Leme7447d7c2016-11-03 18:12:22 -07001706 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
Felipe Lemed071c682016-10-20 16:48:00 -07001707 ds.id_ = ++last_id;
1708 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
1709
1710 MYLOGI("begin\n");
1711
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08001712 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07001713
Felipe Leme75876a22016-10-27 16:31:27 -07001714 if (do_start_service) {
1715 MYLOGI("Starting 'dumpstate' service\n");
1716 android::status_t ret;
1717 if ((ret = android::os::DumpstateService::Start()) != android::OK) {
1718 MYLOGE("Unable to start DumpstateService: %d\n", ret);
1719 }
1720 }
1721
Felipe Lemef0292972016-11-22 13:57:05 -08001722 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07001723 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
1724 }
1725
Felipe Leme7447d7c2016-11-03 18:12:22 -07001726 MYLOGI("dumpstate info: id=%d, args='%s', extra_options= %s)\n", ds.id_, ds.args_.c_str(),
Felipe Lemed071c682016-10-20 16:48:00 -07001727 ds.extra_options_.c_str());
1728
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001729 MYLOGI("bugreport format version: %s\n", ds.version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08001730
Felipe Leme9a523ae2016-10-20 15:10:33 -07001731 ds.do_early_screenshot_ = ds.update_progress_;
Felipe Lemee338bf62015-12-07 14:03:50 -08001732
Christopher Ferrised9354f2014-10-01 17:35:01 -07001733 // If we are going to use a socket, do it as early as possible
1734 // to avoid timeouts from bugreport.
1735 if (use_socket) {
1736 redirect_to_socket(stdout, "dumpstate");
1737 }
1738
Felipe Leme2628e9e2016-04-12 16:36:51 -07001739 if (use_control_socket) {
1740 MYLOGD("Opening control socket\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001741 ds.control_socket_fd_ = open_socket("dumpstate");
1742 ds.update_progress_ = 1;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001743 }
1744
Felipe Leme71bbfc52015-11-23 14:14:51 -08001745 if (is_redirecting) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001746 ds.bugreport_dir_ = dirname(use_outfile);
Felipe Lemef8124bd2016-12-15 08:54:22 -08001747 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
Ian Pedowitz570e6ec2017-03-17 22:36:53 -07001748 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Felipe Lemef8124bd2016-12-15 08:54:22 -08001749 ds.base_name_ = android::base::StringPrintf("%s-%s-%s", basename(use_outfile),
1750 device_name.c_str(), build_id.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08001751 if (do_add_date) {
1752 char date[80];
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001753 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001754 ds.name_ = date;
Felipe Lemead5f6c42015-11-30 14:26:46 -08001755 } else {
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001756 ds.name_ = "undated";
Felipe Leme71bbfc52015-11-23 14:14:51 -08001757 }
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001758
1759 if (telephony_only) {
1760 ds.base_name_ += "-telephony";
1761 }
1762
Felipe Leme71bbfc52015-11-23 14:14:51 -08001763 if (do_fb) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001764 ds.screenshot_path_ = ds.GetPath(".png");
Felipe Leme71bbfc52015-11-23 14:14:51 -08001765 }
Felipe Leme9a523ae2016-10-20 15:10:33 -07001766 ds.tmp_path_ = ds.GetPath(".tmp");
Felipe Leme75876a22016-10-27 16:31:27 -07001767 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
Felipe Leme71bbfc52015-11-23 14:14:51 -08001768
Felipe Lemee844a9d2016-09-21 15:01:39 -07001769 MYLOGD(
1770 "Bugreport dir: %s\n"
1771 "Base name: %s\n"
1772 "Suffix: %s\n"
1773 "Log path: %s\n"
1774 "Temporary path: %s\n"
1775 "Screenshot path: %s\n",
Felipe Leme9a523ae2016-10-20 15:10:33 -07001776 ds.bugreport_dir_.c_str(), ds.base_name_.c_str(), ds.name_.c_str(),
1777 ds.log_path_.c_str(), ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08001778
Felipe Leme1e9edc62015-12-21 16:02:13 -08001779 if (do_zip_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001780 ds.path_ = ds.GetPath(".zip");
1781 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
1782 create_parent_dirs(ds.path_.c_str());
1783 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
Felipe Leme1d486fe2016-10-14 18:06:47 -07001784 if (ds.zip_file == nullptr) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001785 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001786 do_zip_file = 0;
1787 } else {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001788 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001789 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07001790 ds.AddTextZipEntry("version.txt", ds.version_);
Felipe Leme1e9edc62015-12-21 16:02:13 -08001791 }
1792
Felipe Leme9a523ae2016-10-20 15:10:33 -07001793 if (ds.update_progress_) {
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001794 if (do_broadcast) {
1795 // clang-format off
Christopher Tatecfaa07a2017-01-23 12:20:21 -08001796
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001797 std::vector<std::string> am_args = {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001798 "--receiver-permission", "android.permission.DUMP",
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001799 "--es", "android.intent.extra.NAME", ds.name_,
Felipe Lemee844a9d2016-09-21 15:01:39 -07001800 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
Felipe Leme75876a22016-10-27 16:31:27 -07001801 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
Felipe Leme7447d7c2016-11-03 18:12:22 -07001802 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001803 };
1804 // clang-format on
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001805 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001806 }
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001807 if (use_control_socket) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001808 dprintf(ds.control_socket_fd_, "BEGIN:%s\n", ds.path_.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001809 }
Felipe Leme71bbfc52015-11-23 14:14:51 -08001810 }
1811 }
1812
Nick Kralevichf3599b32016-01-25 15:05:16 -08001813 /* read /proc/cmdline before dropping root */
1814 FILE *cmdline = fopen("/proc/cmdline", "re");
1815 if (cmdline) {
1816 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
1817 fclose(cmdline);
1818 }
1819
John Michelau1f794c42012-09-17 11:20:19 -05001820 if (do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08001821 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05001822 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001823
Felipe Leme9a523ae2016-10-20 15:10:33 -07001824 if (do_fb && ds.do_early_screenshot_) {
1825 if (ds.screenshot_path_.empty()) {
Felipe Leme3634a1e2015-12-09 10:11:47 -08001826 // should not have happened
Felipe Lemecbce55d2016-02-08 09:53:18 -08001827 MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
Felipe Leme3634a1e2015-12-09 10:11:47 -08001828 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001829 MYLOGI("taking early screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001830 ds.TakeScreenshot();
Felipe Lemee338bf62015-12-07 14:03:50 -08001831 }
1832 }
1833
Felipe Leme1e9edc62015-12-21 16:02:13 -08001834 if (do_zip_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001835 if (chown(ds.path_.c_str(), AID_SHELL, AID_SHELL)) {
1836 MYLOGE("Unable to change ownership of zip file %s: %s\n", ds.path_.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07001837 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001838 }
1839 }
1840
Felipe Leme71bbfc52015-11-23 14:14:51 -08001841 if (is_redirecting) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001842 redirect_to_file(stderr, const_cast<char*>(ds.log_path_.c_str()));
1843 if (chown(ds.log_path_.c_str(), AID_SHELL, AID_SHELL)) {
1844 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n",
1845 ds.log_path_.c_str(), strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08001846 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001847 /* TODO: rather than generating a text file now and zipping it later,
1848 it would be more efficient to redirect stdout to the zip entry
1849 directly, but the libziparchive doesn't support that option yet. */
Felipe Leme9a523ae2016-10-20 15:10:33 -07001850 redirect_to_file(stdout, const_cast<char*>(ds.tmp_path_.c_str()));
1851 if (chown(ds.tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Leme6fe9db62016-02-12 09:04:16 -08001852 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
Felipe Leme9a523ae2016-10-20 15:10:33 -07001853 ds.tmp_path_.c_str(), strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08001854 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001855 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08001856
1857 // Don't buffer stdout
1858 setvbuf(stdout, nullptr, _IONBF, 0);
1859
Felipe Leme608385d2016-02-01 10:35:38 -08001860 // NOTE: there should be no stdout output until now, otherwise it would break the header.
1861 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08001862 // duration is logged into MYLOG instead.
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001863 ds.PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001864
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001865 if (telephony_only) {
Jayachandran Ca94c7172017-06-10 15:08:12 -07001866 DumpstateTelephonyOnly();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001867 ds.DumpstateBoard();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001868 } else {
1869 // Dumps systrace right away, otherwise it will be filled with unnecessary events.
1870 // First try to dump anrd trace if the daemon is running. Otherwise, dump
1871 // the raw trace.
1872 if (!dump_anrd_trace()) {
1873 dump_systrace();
1874 }
1875
1876 // Invoking the following dumpsys calls before dump_traces() to try and
1877 // keep the system stats as close to its initial state as possible.
Vishnu Nair780b1282017-10-10 13:57:24 -07001878 RunDumpsysCritical();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001879
1880 // TODO: Drop root user and move into dumpstate() once b/28633932 is fixed.
1881 dump_raft();
1882
1883 /* collect stack traces from Dalvik and native processes (needs root) */
1884 dump_traces_path = dump_traces();
1885
1886 /* Run some operations that require root. */
Narayan Kamathbd863722017-06-01 18:50:12 +01001887 tombstone_data.reset(GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping()));
1888 anr_data.reset(GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping()));
Narayan Kamath8f788292017-05-25 13:20:39 +01001889
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001890 ds.AddDir(RECOVERY_DIR, true);
1891 ds.AddDir(RECOVERY_DATA_DIR, true);
1892 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1893 if (!PropertiesHelper::IsUserBuild()) {
1894 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1895 ds.AddDir(PROFILE_DATA_DIR_REF, true);
1896 }
1897 add_mountinfo();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001898 DumpIpTablesAsRoot();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001899
1900 // Capture any IPSec policies in play. No keys are exposed here.
1901 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"},
1902 CommandOptions::WithTimeout(10).Build());
1903
1904 // Run ss as root so we can see socket marks.
1905 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"},
1906 CommandOptions::WithTimeout(10).Build());
1907
Jin Qian3cd671e2017-09-27 18:50:04 -07001908 // Run iotop as root to show top 100 IO threads
1909 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1910
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001911 if (!DropRootUser()) {
1912 return -1;
1913 }
1914
1915 dumpstate();
Zhengyin Qian068ecc72016-08-10 16:48:14 -07001916 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07001917
Felipe Leme55b42a62015-11-10 17:39:08 -08001918 /* close output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08001919 if (is_redirecting) {
Colin Crossf45fa6b2012-03-26 12:38:26 -07001920 fclose(stdout);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001921 }
1922
Felipe Leme6e01fa62015-11-11 19:35:14 -08001923 /* rename or zip the (now complete) .tmp file to its final location */
1924 if (use_outfile) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001925
1926 /* check if user changed the suffix using system properties */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001927 std::string name = android::base::GetProperty(
Felipe Leme75876a22016-10-27 16:31:27 -07001928 android::base::StringPrintf("dumpstate.%d.name", ds.pid_), "");
Felipe Lemead5f6c42015-11-30 14:26:46 -08001929 bool change_suffix= false;
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001930 if (!name.empty()) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001931 /* must whitelist which characters are allowed, otherwise it could cross directories */
1932 std::regex valid_regex("^[-_a-zA-Z0-9]+$");
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001933 if (std::regex_match(name.c_str(), valid_regex)) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001934 change_suffix = true;
1935 } else {
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001936 MYLOGE("invalid suffix provided by user: %s\n", name.c_str());
Felipe Lemead5f6c42015-11-30 14:26:46 -08001937 }
1938 }
1939 if (change_suffix) {
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001940 MYLOGI("changing suffix from %s to %s\n", ds.name_.c_str(), name.c_str());
1941 ds.name_ = name;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001942 if (!ds.screenshot_path_.empty()) {
1943 std::string new_screenshot_path = ds.GetPath(".png");
1944 if (rename(ds.screenshot_path_.c_str(), new_screenshot_path.c_str())) {
1945 MYLOGE("rename(%s, %s): %s\n", ds.screenshot_path_.c_str(),
1946 new_screenshot_path.c_str(), strerror(errno));
Felipe Lemead5f6c42015-11-30 14:26:46 -08001947 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001948 ds.screenshot_path_ = new_screenshot_path;
Felipe Lemead5f6c42015-11-30 14:26:46 -08001949 }
1950 }
1951 }
1952
Felipe Leme6e01fa62015-11-11 19:35:14 -08001953 bool do_text_file = true;
1954 if (do_zip_file) {
Felipe Leme1d486fe2016-10-14 18:06:47 -07001955 if (!ds.FinishZipFile()) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001956 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Felipe Leme6e01fa62015-11-11 19:35:14 -08001957 do_text_file = true;
1958 } else {
1959 do_text_file = false;
Felipe Leme91274352016-02-26 15:03:52 -08001960 // Since zip file is already created, it needs to be renamed.
Felipe Leme9a523ae2016-10-20 15:10:33 -07001961 std::string new_path = ds.GetPath(".zip");
1962 if (ds.path_ != new_path) {
1963 MYLOGD("Renaming zip file from %s to %s\n", ds.path_.c_str(), new_path.c_str());
1964 if (rename(ds.path_.c_str(), new_path.c_str())) {
1965 MYLOGE("rename(%s, %s): %s\n", ds.path_.c_str(), new_path.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07001966 strerror(errno));
Felipe Leme91274352016-02-26 15:03:52 -08001967 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001968 ds.path_ = new_path;
Felipe Leme91274352016-02-26 15:03:52 -08001969 }
1970 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001971 }
1972 }
1973 if (do_text_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001974 ds.path_ = ds.GetPath(".txt");
1975 MYLOGD("Generating .txt bugreport at %s from %s\n", ds.path_.c_str(),
1976 ds.tmp_path_.c_str());
1977 if (rename(ds.tmp_path_.c_str(), ds.path_.c_str())) {
1978 MYLOGE("rename(%s, %s): %s\n", ds.tmp_path_.c_str(), ds.path_.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07001979 strerror(errno));
Felipe Leme9a523ae2016-10-20 15:10:33 -07001980 ds.path_.clear();
Felipe Leme6e01fa62015-11-11 19:35:14 -08001981 }
1982 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07001983 if (use_control_socket) {
1984 if (do_text_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001985 dprintf(ds.control_socket_fd_,
Felipe Lemee844a9d2016-09-21 15:01:39 -07001986 "FAIL:could not create zip file, check %s "
1987 "for more details\n",
Felipe Leme9a523ae2016-10-20 15:10:33 -07001988 ds.log_path_.c_str());
Felipe Leme2628e9e2016-04-12 16:36:51 -07001989 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001990 dprintf(ds.control_socket_fd_, "OK:%s\n", ds.path_.c_str());
Felipe Leme2628e9e2016-04-12 16:36:51 -07001991 }
1992 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001993 }
1994
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08001995 /* vibrate a few but shortly times to let user know it's finished */
Felipe Leme35b8cf12017-02-10 15:47:29 -08001996 for (int i = 0; i < 3; i++) {
1997 Vibrate(75);
1998 usleep((75 + 50) * 1000);
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08001999 }
2000
Jeff Brown1dc94e32014-09-11 14:15:27 -07002001 /* tell activity manager we're done */
Felipe Leme71bbfc52015-11-23 14:14:51 -08002002 if (do_broadcast) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002003 if (!ds.path_.empty()) {
2004 MYLOGI("Final bugreport path: %s\n", ds.path_.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07002005 // clang-format off
Christopher Tatecfaa07a2017-01-23 12:20:21 -08002006
Felipe Leme36b3f6f2015-11-19 15:41:04 -08002007 std::vector<std::string> am_args = {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002008 "--receiver-permission", "android.permission.DUMP",
Felipe Lemee844a9d2016-09-21 15:01:39 -07002009 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
Felipe Leme75876a22016-10-27 16:31:27 -07002010 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
Felipe Leme7447d7c2016-11-03 18:12:22 -07002011 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
Felipe Leme9a523ae2016-10-20 15:10:33 -07002012 "--es", "android.intent.extra.BUGREPORT", ds.path_,
2013 "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_
Felipe Leme36b3f6f2015-11-19 15:41:04 -08002014 };
Felipe Lemeaabfcae2016-07-29 09:49:04 -07002015 // clang-format on
Felipe Leme36b3f6f2015-11-19 15:41:04 -08002016 if (do_fb) {
2017 am_args.push_back("--es");
2018 am_args.push_back("android.intent.extra.SCREENSHOT");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002019 am_args.push_back(ds.screenshot_path_);
Felipe Leme36b3f6f2015-11-19 15:41:04 -08002020 }
Naveen Kallab53a1c92017-03-16 18:17:25 -07002021 if (!ds.notification_title.empty()) {
2022 am_args.push_back("--es");
2023 am_args.push_back("android.intent.extra.TITLE");
2024 am_args.push_back(ds.notification_title);
2025 if (!ds.notification_description.empty()) {
2026 am_args.push_back("--es");
2027 am_args.push_back("android.intent.extra.DESCRIPTION");
2028 am_args.push_back(ds.notification_description);
2029 }
2030 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00002031 if (is_remote_mode) {
2032 am_args.push_back("--es");
2033 am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002034 am_args.push_back(SHA256_file_hash(ds.path_));
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002035 SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED",
2036 am_args);
Michal Karpinski4db754f2015-12-11 18:04:32 +00002037 } else {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002038 SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args);
Michal Karpinski4db754f2015-12-11 18:04:32 +00002039 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08002040 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002041 MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
Felipe Leme6e01fa62015-11-11 19:35:14 -08002042 }
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07002043 }
2044
Felipe Leme7447d7c2016-11-03 18:12:22 -07002045 MYLOGD("Final progress: %d/%d (estimated %d)\n", ds.progress_->Get(), ds.progress_->GetMax(),
2046 ds.progress_->GetInitialMax());
2047 ds.progress_->Save();
2048 MYLOGI("done (id %d)\n", ds.id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002049
Felipe Leme107a05f2016-03-08 15:11:15 -08002050 if (is_redirecting) {
2051 fclose(stderr);
2052 }
2053
Felipe Leme9a523ae2016-10-20 15:10:33 -07002054 if (use_control_socket && ds.control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07002055 MYLOGD("Closing control socket\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002056 close(ds.control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07002057 }
2058
Narayan Kamath6b9516c2017-10-27 11:15:51 +01002059 CloseDumpFds(tombstone_data.get());
2060 CloseDumpFds(anr_data.get());
2061
Colin Crossf45fa6b2012-03-26 12:38:26 -07002062 return 0;
2063}