1 /*
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 */
16
17 #define LOG_TAG "dumpstate"
18
19 #include <dirent.h>
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <libgen.h>
23 #include <limits.h>
24 #include <stdbool.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <sys/poll.h>
29 #include <sys/prctl.h>
30 #include <sys/resource.h>
31 #include <sys/stat.h>
32 #include <sys/time.h>
33 #include <sys/wait.h>
34 #include <unistd.h>
35
36 #include <chrono>
37 #include <functional>
38 #include <future>
39 #include <memory>
40 #include <regex>
41 #include <set>
42 #include <string>
43 #include <utility>
44 #include <vector>
45
46 #include <android-base/file.h>
47 #include <android-base/properties.h>
48 #include <android-base/scopeguard.h>
49 #include <android-base/stringprintf.h>
50 #include <android-base/strings.h>
51 #include <android-base/unique_fd.h>
52 #include <android/hardware/dumpstate/1.0/IDumpstateDevice.h>
53 #include <android/hidl/manager/1.0/IServiceManager.h>
54 #include <cutils/native_handle.h>
55 #include <cutils/properties.h>
56 #include <dumpsys.h>
57 #include <hidl/ServiceManagement.h>
58 #include <openssl/sha.h>
59 #include <private/android_filesystem_config.h>
60 #include <private/android_logger.h>
61 #include <serviceutils/PriorityDumper.h>
62 #include <utils/StrongPointer.h>
63 #include "DumpstateInternal.h"
64 #include "DumpstateSectionReporter.h"
65 #include "DumpstateService.h"
66 #include "dumpstate.h"
67
68 using ::android::hardware::dumpstate::V1_0::IDumpstateDevice;
69 using ::std::literals::chrono_literals::operator""ms;
70 using ::std::literals::chrono_literals::operator""s;
71
72 // TODO: remove once moved to namespace
73 using android::defaultServiceManager;
74 using android::Dumpsys;
75 using android::INVALID_OPERATION;
76 using android::IServiceManager;
77 using android::OK;
78 using android::sp;
79 using android::status_t;
80 using android::String16;
81 using android::String8;
82 using android::TIMED_OUT;
83 using android::UNKNOWN_ERROR;
84 using android::Vector;
85 using android::os::dumpstate::CommandOptions;
86 using android::os::dumpstate::DumpFileToFd;
87 using android::os::dumpstate::DumpstateSectionReporter;
88 using android::os::dumpstate::GetPidByName;
89 using android::os::dumpstate::PropertiesHelper;
90
91 /* read before root is shed */
92 static char cmdline_buf[16384] = "(unknown)";
93 static const char *dump_traces_path = NULL;
94
95 // TODO: variables and functions below should be part of dumpstate object
96
97 static std::set<std::string> mount_points;
98 void add_mountinfo();
99
100 #define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
101 #define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
102 #define BLK_DEV_SYS_DIR "/sys/block"
103
104 #define RAFT_DIR "/data/misc/raft"
105 #define RECOVERY_DIR "/cache/recovery"
106 #define RECOVERY_DATA_DIR "/data/misc/recovery"
107 #define UPDATE_ENGINE_LOG_DIR "/data/misc/update_engine_log"
108 #define LOGPERSIST_DATA_DIR "/data/misc/logd"
109 #define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
110 #define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
111 #define WLUTIL "/vendor/xbin/wlutil"
112 #define WMTRACE_DATA_DIR "/data/misc/wmtrace"
113
114 // TODO(narayan): Since this information has to be kept in sync
115 // with tombstoned, we should just put it in a common header.
116 //
117 // File: system/core/debuggerd/tombstoned/tombstoned.cpp
118 static const std::string TOMBSTONE_DIR = "/data/tombstones/";
119 static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
120 static const std::string ANR_DIR = "/data/anr/";
121 static const std::string ANR_FILE_PREFIX = "anr_";
122
123 // TODO: temporary variables and functions used during C++ refactoring
124 static Dumpstate& ds = Dumpstate::GetInstance();
RunCommand(const std::string & title,const std::vector<std::string> & fullCommand,const CommandOptions & options=CommandOptions::DEFAULT)125 static int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand,
126 const CommandOptions& options = CommandOptions::DEFAULT) {
127 return ds.RunCommand(title, fullCommand, options);
128 }
RunDumpsys(const std::string & title,const std::vector<std::string> & dumpsysArgs,const CommandOptions & options=Dumpstate::DEFAULT_DUMPSYS,long dumpsysTimeoutMs=0)129 static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
130 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
131 long dumpsysTimeoutMs = 0) {
132 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs);
133 }
DumpFile(const std::string & title,const std::string & path)134 static int DumpFile(const std::string& title, const std::string& path) {
135 return ds.DumpFile(title, path);
136 }
137
138 // Relative directory (inside the zip) for all files copied as-is into the bugreport.
139 static const std::string ZIP_ROOT_DIR = "FS";
140
141 // Must be hardcoded because dumpstate HAL implementation need SELinux access to it
142 static const std::string kDumpstateBoardPath = "/bugreports/";
143 static const std::string kProtoPath = "proto/";
144 static const std::string kProtoExt = ".proto";
145 static const std::string kDumpstateBoardFiles[] = {
146 "dumpstate_board.txt",
147 "dumpstate_board.bin"
148 };
149 static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
150
151 static constexpr char PROPERTY_EXTRA_OPTIONS[] = "dumpstate.options";
152 static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
153 static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
154 static constexpr char PROPERTY_EXTRA_TITLE[] = "dumpstate.options.title";
155 static constexpr char PROPERTY_EXTRA_DESCRIPTION[] = "dumpstate.options.description";
156
157 static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
158
159 /*
160 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
161 * The returned vector is sorted by the mtimes of the dumps. If |limit_by_mtime|
162 * is set, the vector only contains files that were written in the last 30 minutes.
163 * If |limit_by_count| is set, the vector only contains the ten latest files.
164 */
GetDumpFds(const std::string & dir_path,const std::string & file_prefix,bool limit_by_mtime,bool limit_by_count=true)165 static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
166 const std::string& file_prefix,
167 bool limit_by_mtime,
168 bool limit_by_count = true) {
169 const time_t thirty_minutes_ago = ds.now_ - 60 * 30;
170
171 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
172
173 if (dump_dir == nullptr) {
174 MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno));
175 return std::vector<DumpData>();
176 }
177
178 std::vector<DumpData> dump_data;
179 struct dirent* entry = nullptr;
180 while ((entry = readdir(dump_dir.get()))) {
181 if (entry->d_type != DT_REG) {
182 continue;
183 }
184
185 const std::string base_name(entry->d_name);
186 if (base_name.find(file_prefix) != 0) {
187 continue;
188 }
189
190 const std::string abs_path = dir_path + base_name;
191 android::base::unique_fd fd(
192 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
193 if (fd == -1) {
194 MYLOGW("Unable to open dump file %s: %s\n", abs_path.c_str(), strerror(errno));
195 break;
196 }
197
198 struct stat st = {};
199 if (fstat(fd, &st) == -1) {
200 MYLOGW("Unable to stat dump file %s: %s\n", abs_path.c_str(), strerror(errno));
201 continue;
202 }
203
204 if (limit_by_mtime && st.st_mtime < thirty_minutes_ago) {
205 MYLOGI("Excluding stale dump file: %s\n", abs_path.c_str());
206 continue;
207 }
208
209 dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
210 }
211
212 // Sort in descending modification time so that we only keep the newest
213 // reports if |limit_by_count| is true.
214 std::sort(dump_data.begin(), dump_data.end(),
215 [](const DumpData& d1, const DumpData& d2) { return d1.mtime > d2.mtime; });
216
217 if (limit_by_count && dump_data.size() > 10) {
218 dump_data.erase(dump_data.begin() + 10, dump_data.end());
219 }
220
221 return dump_data;
222 }
223
AddDumps(const std::vector<DumpData>::const_iterator start,const std::vector<DumpData>::const_iterator end,const char * type_name,const bool add_to_zip)224 static bool AddDumps(const std::vector<DumpData>::const_iterator start,
225 const std::vector<DumpData>::const_iterator end,
226 const char* type_name, const bool add_to_zip) {
227 bool dumped = false;
228 for (auto it = start; it != end; ++it) {
229 const std::string& name = it->name;
230 const int fd = it->fd;
231 dumped = true;
232
233 // Seek to the beginning of the file before dumping any data. A given
234 // DumpData entry might be dumped multiple times in the report.
235 //
236 // For example, the most recent ANR entry is dumped to the body of the
237 // main entry and it also shows up as a separate entry in the bugreport
238 // ZIP file.
239 if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) {
240 MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(),
241 strerror(errno));
242 }
243
244 if (ds.IsZipping() && add_to_zip) {
245 if (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd, /* timeout = */ 0ms) != OK) {
246 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
247 }
248 } else {
249 dump_file_from_fd(type_name, name.c_str(), fd);
250 }
251 }
252
253 return dumped;
254 }
255
256 // for_each_pid() callback to get mount info about a process.
do_mountinfo(int pid,const char * name)257 void do_mountinfo(int pid, const char* name __attribute__((unused))) {
258 char path[PATH_MAX];
259
260 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
261 // are added.
262 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
263 char linkname[PATH_MAX];
264 ssize_t r = readlink(path, linkname, PATH_MAX);
265 if (r == -1) {
266 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
267 return;
268 }
269 linkname[r] = '\0';
270
271 if (mount_points.find(linkname) == mount_points.end()) {
272 // First time this mount point was found: add it
273 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
274 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
275 mount_points.insert(linkname);
276 } else {
277 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
278 }
279 }
280 }
281
add_mountinfo()282 void add_mountinfo() {
283 if (!ds.IsZipping()) return;
284 std::string title = "MOUNT INFO";
285 mount_points.clear();
286 DurationReporter duration_reporter(title, true);
287 for_each_pid(do_mountinfo, nullptr);
288 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
289 }
290
dump_dev_files(const char * title,const char * driverpath,const char * filename)291 static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
292 {
293 DIR *d;
294 struct dirent *de;
295 char path[PATH_MAX];
296
297 d = opendir(driverpath);
298 if (d == NULL) {
299 return;
300 }
301
302 while ((de = readdir(d))) {
303 if (de->d_type != DT_LNK) {
304 continue;
305 }
306 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
307 DumpFile(title, path);
308 }
309
310 closedir(d);
311 }
312
313
314
315 // dump anrd's trace and add to the zip file.
316 // 1. check if anrd is running on this device.
317 // 2. send a SIGUSR1 to its pid which will dump anrd's trace.
318 // 3. wait until the trace generation completes and add to the zip file.
dump_anrd_trace()319 static bool dump_anrd_trace() {
320 unsigned int pid;
321 char buf[50], path[PATH_MAX];
322 struct dirent *trace;
323 struct stat st;
324 DIR *trace_dir;
325 int retry = 5;
326 long max_ctime = 0, old_mtime;
327 long long cur_size = 0;
328 const char *trace_path = "/data/misc/anrd/";
329
330 if (!ds.IsZipping()) {
331 MYLOGE("Not dumping anrd trace because it's not a zipped bugreport\n");
332 return false;
333 }
334
335 // find anrd's pid if it is running.
336 pid = GetPidByName("/system/xbin/anrd");
337
338 if (pid > 0) {
339 if (stat(trace_path, &st) == 0) {
340 old_mtime = st.st_mtime;
341 } else {
342 MYLOGE("Failed to find: %s\n", trace_path);
343 return false;
344 }
345
346 // send SIGUSR1 to the anrd to generate a trace.
347 sprintf(buf, "%u", pid);
348 if (RunCommand("ANRD_DUMP", {"kill", "-SIGUSR1", buf},
349 CommandOptions::WithTimeout(1).Build())) {
350 MYLOGE("anrd signal timed out. Please manually collect trace\n");
351 return false;
352 }
353
354 while (retry-- > 0 && old_mtime == st.st_mtime) {
355 sleep(1);
356 stat(trace_path, &st);
357 }
358
359 if (retry < 0 && old_mtime == st.st_mtime) {
360 MYLOGE("Failed to stat %s or trace creation timeout\n", trace_path);
361 return false;
362 }
363
364 // identify the trace file by its creation time.
365 if (!(trace_dir = opendir(trace_path))) {
366 MYLOGE("Can't open trace file under %s\n", trace_path);
367 }
368 while ((trace = readdir(trace_dir))) {
369 if (strcmp(trace->d_name, ".") == 0
370 || strcmp(trace->d_name, "..") == 0) {
371 continue;
372 }
373 sprintf(path, "%s%s", trace_path, trace->d_name);
374 if (stat(path, &st) == 0) {
375 if (st.st_ctime > max_ctime) {
376 max_ctime = st.st_ctime;
377 sprintf(buf, "%s", trace->d_name);
378 }
379 }
380 }
381 closedir(trace_dir);
382
383 // Wait until the dump completes by checking the size of the trace.
384 if (max_ctime > 0) {
385 sprintf(path, "%s%s", trace_path, buf);
386 while(true) {
387 sleep(1);
388 if (stat(path, &st) == 0) {
389 if (st.st_size == cur_size) {
390 break;
391 } else if (st.st_size > cur_size) {
392 cur_size = st.st_size;
393 } else {
394 return false;
395 }
396 } else {
397 MYLOGE("Cant stat() %s anymore\n", path);
398 return false;
399 }
400 }
401 // Add to the zip file.
402 if (!ds.AddZipEntry("anrd_trace.txt", path)) {
403 MYLOGE("Unable to add anrd_trace file %s to zip file\n", path);
404 } else {
405 if (remove(path)) {
406 MYLOGE("Error removing anrd_trace file %s: %s", path, strerror(errno));
407 }
408 return true;
409 }
410 } else {
411 MYLOGE("Can't stats any trace file under %s\n", trace_path);
412 }
413 }
414 return false;
415 }
416
dump_systrace()417 static void dump_systrace() {
418 if (!ds.IsZipping()) {
419 MYLOGD("Not dumping systrace because it's not a zipped bugreport\n");
420 return;
421 }
422 std::string systrace_path = ds.GetPath("-systrace.txt");
423 if (systrace_path.empty()) {
424 MYLOGE("Not dumping systrace because path is empty\n");
425 return;
426 }
427 const char* path = "/sys/kernel/debug/tracing/tracing_on";
428 long int is_tracing;
429 if (read_file_as_long(path, &is_tracing)) {
430 return; // error already logged
431 }
432 if (is_tracing <= 0) {
433 MYLOGD("Skipping systrace because '%s' content is '%ld'\n", path, is_tracing);
434 return;
435 }
436
437 MYLOGD("Running '/system/bin/atrace --async_dump -o %s', which can take several minutes",
438 systrace_path.c_str());
439 if (RunCommand("SYSTRACE", {"/system/bin/atrace", "--async_dump", "-o", systrace_path},
440 CommandOptions::WithTimeout(120).Build())) {
441 MYLOGE("systrace timed out, its zip entry will be incomplete\n");
442 // TODO: RunCommand tries to kill the process, but atrace doesn't die
443 // peacefully; ideally, we should call strace to stop itself, but there is no such option
444 // yet (just a --async_stop, which stops and dump
445 // if (RunCommand("SYSTRACE", {"/system/bin/atrace", "--kill"})) {
446 // MYLOGE("could not stop systrace ");
447 // }
448 }
449 if (!ds.AddZipEntry("systrace.txt", systrace_path)) {
450 MYLOGE("Unable to add systrace file %s to zip file\n", systrace_path.c_str());
451 } else {
452 if (remove(systrace_path.c_str())) {
453 MYLOGE("Error removing systrace file %s: %s", systrace_path.c_str(), strerror(errno));
454 }
455 }
456 }
457
dump_raft()458 static void dump_raft() {
459 if (PropertiesHelper::IsUserBuild()) {
460 return;
461 }
462
463 std::string raft_path = ds.GetPath("-raft_log.txt");
464 if (raft_path.empty()) {
465 MYLOGD("raft_path is empty\n");
466 return;
467 }
468
469 struct stat s;
470 if (stat(RAFT_DIR, &s) != 0 || !S_ISDIR(s.st_mode)) {
471 MYLOGD("%s does not exist or is not a directory\n", RAFT_DIR);
472 return;
473 }
474
475 CommandOptions options = CommandOptions::WithTimeout(600).Build();
476 if (!ds.IsZipping()) {
477 // Write compressed and encoded raft logs to stdout if it's not a zipped bugreport.
478 RunCommand("RAFT LOGS", {"logcompressor", "-r", RAFT_DIR}, options);
479 return;
480 }
481
482 RunCommand("RAFT LOGS", {"logcompressor", "-n", "-r", RAFT_DIR, "-o", raft_path}, options);
483 if (!ds.AddZipEntry("raft_log.txt", raft_path)) {
484 MYLOGE("Unable to add raft log %s to zip file\n", raft_path.c_str());
485 } else {
486 if (remove(raft_path.c_str())) {
487 MYLOGE("Error removing raft file %s: %s\n", raft_path.c_str(), strerror(errno));
488 }
489 }
490 }
491
skip_not_stat(const char * path)492 static bool skip_not_stat(const char *path) {
493 static const char stat[] = "/stat";
494 size_t len = strlen(path);
495 if (path[len - 1] == '/') { /* Directory? */
496 return false;
497 }
498 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
499 }
500
skip_none(const char * path)501 static bool skip_none(const char* path __attribute__((unused))) {
502 return false;
503 }
504
505 unsigned long worst_write_perf = 20000; /* in KB/s */
506
507 //
508 // stat offsets
509 // Name units description
510 // ---- ----- -----------
511 // read I/Os requests number of read I/Os processed
512 #define __STAT_READ_IOS 0
513 // read merges requests number of read I/Os merged with in-queue I/O
514 #define __STAT_READ_MERGES 1
515 // read sectors sectors number of sectors read
516 #define __STAT_READ_SECTORS 2
517 // read ticks milliseconds total wait time for read requests
518 #define __STAT_READ_TICKS 3
519 // write I/Os requests number of write I/Os processed
520 #define __STAT_WRITE_IOS 4
521 // write merges requests number of write I/Os merged with in-queue I/O
522 #define __STAT_WRITE_MERGES 5
523 // write sectors sectors number of sectors written
524 #define __STAT_WRITE_SECTORS 6
525 // write ticks milliseconds total wait time for write requests
526 #define __STAT_WRITE_TICKS 7
527 // in_flight requests number of I/Os currently in flight
528 #define __STAT_IN_FLIGHT 8
529 // io_ticks milliseconds total time this block device has been active
530 #define __STAT_IO_TICKS 9
531 // time_in_queue milliseconds total wait time for all requests
532 #define __STAT_IN_QUEUE 10
533 #define __STAT_NUMBER_FIELD 11
534 //
535 // read I/Os, write I/Os
536 // =====================
537 //
538 // These values increment when an I/O request completes.
539 //
540 // read merges, write merges
541 // =========================
542 //
543 // These values increment when an I/O request is merged with an
544 // already-queued I/O request.
545 //
546 // read sectors, write sectors
547 // ===========================
548 //
549 // These values count the number of sectors read from or written to this
550 // block device. The "sectors" in question are the standard UNIX 512-byte
551 // sectors, not any device- or filesystem-specific block size. The
552 // counters are incremented when the I/O completes.
553 #define SECTOR_SIZE 512
554 //
555 // read ticks, write ticks
556 // =======================
557 //
558 // These values count the number of milliseconds that I/O requests have
559 // waited on this block device. If there are multiple I/O requests waiting,
560 // these values will increase at a rate greater than 1000/second; for
561 // example, if 60 read requests wait for an average of 30 ms, the read_ticks
562 // field will increase by 60*30 = 1800.
563 //
564 // in_flight
565 // =========
566 //
567 // This value counts the number of I/O requests that have been issued to
568 // the device driver but have not yet completed. It does not include I/O
569 // requests that are in the queue but not yet issued to the device driver.
570 //
571 // io_ticks
572 // ========
573 //
574 // This value counts the number of milliseconds during which the device has
575 // had I/O requests queued.
576 //
577 // time_in_queue
578 // =============
579 //
580 // This value counts the number of milliseconds that I/O requests have waited
581 // on this block device. If there are multiple I/O requests waiting, this
582 // value will increase as the product of the number of milliseconds times the
583 // number of requests waiting (see "read ticks" above for an example).
584 #define S_TO_MS 1000
585 //
586
dump_stat_from_fd(const char * title __unused,const char * path,int fd)587 static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
588 unsigned long long fields[__STAT_NUMBER_FIELD];
589 bool z;
590 char *cp, *buffer = NULL;
591 size_t i = 0;
592 FILE *fp = fdopen(fd, "rb");
593 getline(&buffer, &i, fp);
594 fclose(fp);
595 if (!buffer) {
596 return -errno;
597 }
598 i = strlen(buffer);
599 while ((i > 0) && (buffer[i - 1] == '\n')) {
600 buffer[--i] = '\0';
601 }
602 if (!*buffer) {
603 free(buffer);
604 return 0;
605 }
606 z = true;
607 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
608 fields[i] = strtoull(cp, &cp, 10);
609 if (fields[i] != 0) {
610 z = false;
611 }
612 }
613 if (z) { /* never accessed */
614 free(buffer);
615 return 0;
616 }
617
618 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
619 path += sizeof(BLK_DEV_SYS_DIR) - 1;
620 }
621
622 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
623 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
624 "W-wait", "in-fli", "activ", "T-wait", path, buffer);
625 free(buffer);
626
627 if (fields[__STAT_IO_TICKS]) {
628 unsigned long read_perf = 0;
629 unsigned long read_ios = 0;
630 if (fields[__STAT_READ_TICKS]) {
631 unsigned long long divisor = fields[__STAT_READ_TICKS]
632 * fields[__STAT_IO_TICKS];
633 read_perf = ((unsigned long long)SECTOR_SIZE
634 * fields[__STAT_READ_SECTORS]
635 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
636 / divisor;
637 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
638 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
639 / divisor;
640 }
641
642 unsigned long write_perf = 0;
643 unsigned long write_ios = 0;
644 if (fields[__STAT_WRITE_TICKS]) {
645 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
646 * fields[__STAT_IO_TICKS];
647 write_perf = ((unsigned long long)SECTOR_SIZE
648 * fields[__STAT_WRITE_SECTORS]
649 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
650 / divisor;
651 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
652 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
653 / divisor;
654 }
655
656 unsigned queue = (fields[__STAT_IN_QUEUE]
657 + (fields[__STAT_IO_TICKS] >> 1))
658 / fields[__STAT_IO_TICKS];
659
660 if (!write_perf && !write_ios) {
661 printf("%-30s: perf(ios) rd: %luKB/s(%lu/s) q: %u\n", path, read_perf, read_ios, queue);
662 } else {
663 printf("%-30s: perf(ios) rd: %luKB/s(%lu/s) wr: %luKB/s(%lu/s) q: %u\n", path, read_perf,
664 read_ios, write_perf, write_ios, queue);
665 }
666
667 /* bugreport timeout factor adjustment */
668 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
669 worst_write_perf = write_perf;
670 }
671 }
672 return 0;
673 }
674
675 static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
676
677 /* timeout in ms to read a list of buffers */
logcat_timeout(const std::vector<std::string> & buffers)678 static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
679 unsigned long timeout_ms = 0;
680 for (const auto& buffer : buffers) {
681 log_id_t id = android_name_to_log_id(buffer.c_str());
682 unsigned long property_size = __android_logger_get_buffer_size(id);
683 /* Engineering margin is ten-fold our guess */
684 timeout_ms += 10 * (property_size + worst_write_perf) / worst_write_perf;
685 }
686 return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
687 }
688
PrintHeader() const689 void Dumpstate::PrintHeader() const {
690 std::string build, fingerprint, radio, bootloader, network;
691 char date[80];
692
693 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
694 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
695 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
696 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
697 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
698 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
699
700 printf("========================================================\n");
701 printf("== dumpstate: %s\n", date);
702 printf("========================================================\n");
703
704 printf("\n");
705 printf("Build: %s\n", build.c_str());
706 // NOTE: fingerprint entry format is important for other tools.
707 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
708 printf("Bootloader: %s\n", bootloader.c_str());
709 printf("Radio: %s\n", radio.c_str());
710 printf("Network: %s\n", network.c_str());
711
712 printf("Kernel: ");
713 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
714 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
715 printf("Uptime: ");
716 RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"},
717 CommandOptions::WithTimeout(1).Always().Build());
718 printf("Bugreport format version: %s\n", version_.c_str());
719 printf("Dumpstate info: id=%d pid=%d dry_run=%d args=%s extra_options=%s\n", id_, pid_,
720 PropertiesHelper::IsDryRun(), args_.c_str(), extra_options_.c_str());
721 printf("\n");
722 }
723
724 // List of file extensions that can cause a zip file attachment to be rejected by some email
725 // service providers.
726 static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
727 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
728 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
729 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
730 };
731
AddZipEntryFromFd(const std::string & entry_name,int fd,std::chrono::milliseconds timeout=0ms)732 status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd,
733 std::chrono::milliseconds timeout = 0ms) {
734 if (!IsZipping()) {
735 MYLOGD("Not adding zip entry %s from fd because it's not a zipped bugreport\n",
736 entry_name.c_str());
737 return INVALID_OPERATION;
738 }
739 std::string valid_name = entry_name;
740
741 // Rename extension if necessary.
742 size_t idx = entry_name.rfind('.');
743 if (idx != std::string::npos) {
744 std::string extension = entry_name.substr(idx);
745 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
746 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
747 valid_name = entry_name + ".renamed";
748 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
749 }
750 }
751
752 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
753 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
754 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), ZipWriter::kCompress,
755 get_mtime(fd, ds.now_));
756 if (err != 0) {
757 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
758 ZipWriter::ErrorCodeString(err));
759 return UNKNOWN_ERROR;
760 }
761 auto start = std::chrono::steady_clock::now();
762 auto end = start + timeout;
763 struct pollfd pfd = {fd, POLLIN};
764
765 std::vector<uint8_t> buffer(65536);
766 while (1) {
767 if (timeout.count() > 0) {
768 // lambda to recalculate the timeout.
769 auto time_left_ms = [end]() {
770 auto now = std::chrono::steady_clock::now();
771 auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
772 return std::max(diff.count(), 0LL);
773 };
774
775 int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
776 if (rc < 0) {
777 MYLOGE("Error in poll while adding from fd to zip entry %s:%s", entry_name.c_str(),
778 strerror(errno));
779 return -errno;
780 } else if (rc == 0) {
781 MYLOGE("Timed out adding from fd to zip entry %s:%s Timeout:%lldms",
782 entry_name.c_str(), strerror(errno), timeout.count());
783 return TIMED_OUT;
784 }
785 }
786
787 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
788 if (bytes_read == 0) {
789 break;
790 } else if (bytes_read == -1) {
791 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
792 return -errno;
793 }
794 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
795 if (err) {
796 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
797 return UNKNOWN_ERROR;
798 }
799 }
800
801 err = zip_writer_->FinishEntry();
802 if (err != 0) {
803 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
804 return UNKNOWN_ERROR;
805 }
806
807 return OK;
808 }
809
AddZipEntry(const std::string & entry_name,const std::string & entry_path)810 bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
811 android::base::unique_fd fd(
812 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
813 if (fd == -1) {
814 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
815 return false;
816 }
817
818 return (AddZipEntryFromFd(entry_name, fd.get()) == OK);
819 }
820
821 /* adds a file to the existing zipped bugreport */
_add_file_from_fd(const char * title,const char * path,int fd)822 static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
823 return (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) == OK) ? 0 : 1;
824 }
825
AddDir(const std::string & dir,bool recursive)826 void Dumpstate::AddDir(const std::string& dir, bool recursive) {
827 if (!IsZipping()) {
828 MYLOGD("Not adding dir %s because it's not a zipped bugreport\n", dir.c_str());
829 return;
830 }
831 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
832 DurationReporter duration_reporter(dir, true);
833 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
834 }
835
AddTextZipEntry(const std::string & entry_name,const std::string & content)836 bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
837 if (!IsZipping()) {
838 MYLOGD("Not adding text zip entry %s because it's not a zipped bugreport\n",
839 entry_name.c_str());
840 return false;
841 }
842 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
843 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, ds.now_);
844 if (err != 0) {
845 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
846 ZipWriter::ErrorCodeString(err));
847 return false;
848 }
849
850 err = zip_writer_->WriteBytes(content.c_str(), content.length());
851 if (err != 0) {
852 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
853 ZipWriter::ErrorCodeString(err));
854 return false;
855 }
856
857 err = zip_writer_->FinishEntry();
858 if (err != 0) {
859 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
860 return false;
861 }
862
863 return true;
864 }
865
DoKmsg()866 static void DoKmsg() {
867 struct stat st;
868 if (!stat(PSTORE_LAST_KMSG, &st)) {
869 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
870 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
871 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
872 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
873 } else {
874 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
875 DumpFile("LAST KMSG", "/proc/last_kmsg");
876 }
877 }
878
DoKernelLogcat()879 static void DoKernelLogcat() {
880 unsigned long timeout_ms = logcat_timeout({"kernel"});
881 RunCommand(
882 "KERNEL LOG",
883 {"logcat", "-b", "kernel", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
884 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
885 }
886
DoLogcat()887 static void DoLogcat() {
888 unsigned long timeout_ms;
889 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
890 // calculate timeout
891 timeout_ms = logcat_timeout({"main", "system", "crash"});
892 RunCommand("SYSTEM LOG",
893 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
894 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
895 timeout_ms = logcat_timeout({"events"});
896 RunCommand(
897 "EVENT LOG",
898 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
899 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
900 timeout_ms = logcat_timeout({"stats"});
901 RunCommand(
902 "STATS LOG",
903 {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
904 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
905 timeout_ms = logcat_timeout({"radio"});
906 RunCommand(
907 "RADIO LOG",
908 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
909 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
910
911 RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
912
913 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
914 RunCommand("LAST LOGCAT", {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable",
915 "-v", "uid", "-d", "*:v"});
916 }
917
DumpIpTablesAsRoot()918 static void DumpIpTablesAsRoot() {
919 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
920 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
921 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
922 /* no ip6 nat */
923 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
924 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
925 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
926 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
927 }
928
AddGlobalAnrTraceFile(const bool add_to_zip,const std::string & anr_traces_file,const std::string & anr_traces_dir)929 static void AddGlobalAnrTraceFile(const bool add_to_zip, const std::string& anr_traces_file,
930 const std::string& anr_traces_dir) {
931 std::string dump_traces_dir;
932
933 if (dump_traces_path != nullptr) {
934 if (add_to_zip) {
935 dump_traces_dir = dirname(dump_traces_path);
936 MYLOGD("Adding ANR traces (directory %s) to the zip file\n", dump_traces_dir.c_str());
937 ds.AddDir(dump_traces_dir, true);
938 } else {
939 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
940 dump_traces_path);
941 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
942 }
943 }
944
945
946 // Make sure directory is not added twice.
947 // TODO: this is an overzealous check because it's relying on dump_traces_path - which is
948 // generated by dump_traces() - and anr_traces_path - which is retrieved from a system
949 // property - but in reality they're the same path (although the former could be nullptr).
950 // Anyways, once dump_traces() is refactored as a private Dumpstate function, this logic should
951 // be revisited.
952 bool already_dumped = anr_traces_dir == dump_traces_dir;
953
954 MYLOGD("AddGlobalAnrTraceFile(): dump_traces_dir=%s, anr_traces_dir=%s, already_dumped=%d\n",
955 dump_traces_dir.c_str(), anr_traces_dir.c_str(), already_dumped);
956
957 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
958 open(anr_traces_file.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
959 if (fd.get() < 0) {
960 printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_file.c_str(), strerror(errno));
961 } else {
962 if (add_to_zip) {
963 if (!already_dumped) {
964 MYLOGD("Adding dalvik ANR traces (directory %s) to the zip file\n",
965 anr_traces_dir.c_str());
966 ds.AddDir(anr_traces_dir, true);
967 }
968 } else {
969 MYLOGD("Dumping last ANR traces (%s) to the main bugreport entry\n",
970 anr_traces_file.c_str());
971 dump_file_from_fd("VM TRACES AT LAST ANR", anr_traces_file.c_str(), fd.get());
972 }
973 }
974 }
975
AddAnrTraceDir(const bool add_to_zip,const std::string & anr_traces_dir)976 static void AddAnrTraceDir(const bool add_to_zip, const std::string& anr_traces_dir) {
977 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
978 anr_traces_dir.c_str());
979
980 // If we're here, dump_traces_path will always be a temporary file
981 // (created with mkostemp or similar) that contains dumps taken earlier
982 // on in the process.
983 if (dump_traces_path != nullptr) {
984 if (add_to_zip) {
985 ds.AddZipEntry(ZIP_ROOT_DIR + anr_traces_dir + "/traces-just-now.txt", dump_traces_path);
986 } else {
987 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
988 dump_traces_path);
989 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
990 }
991
992 const int ret = unlink(dump_traces_path);
993 if (ret == -1) {
994 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
995 strerror(errno));
996 }
997 }
998
999 // Add a specific message for the first ANR Dump.
1000 if (ds.anr_data_.size() > 0) {
1001 AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1,
1002 "VM TRACES AT LAST ANR", add_to_zip);
1003
1004 // The "last" ANR will always be included as separate entry in the zip file. In addition,
1005 // it will be present in the body of the main entry if |add_to_zip| == false.
1006 //
1007 // Historical ANRs are always included as separate entries in the bugreport zip file.
1008 AddDumps(ds.anr_data_.begin() + ((add_to_zip) ? 1 : 0), ds.anr_data_.end(),
1009 "HISTORICAL ANR", true /* add_to_zip */);
1010 } else {
1011 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
1012 }
1013 }
1014
AddAnrTraceFiles()1015 static void AddAnrTraceFiles() {
1016 const bool add_to_zip = ds.IsZipping() && ds.version_ == VERSION_SPLIT_ANR;
1017
1018 std::string anr_traces_file;
1019 std::string anr_traces_dir;
1020 bool is_global_trace_file = true;
1021
1022 // First check whether the stack-trace-dir property is set. When it's set,
1023 // each ANR trace will be written to a separate file and not to a global
1024 // stack trace file.
1025 anr_traces_dir = android::base::GetProperty("dalvik.vm.stack-trace-dir", "");
1026 if (anr_traces_dir.empty()) {
1027 anr_traces_file = android::base::GetProperty("dalvik.vm.stack-trace-file", "");
1028 if (!anr_traces_file.empty()) {
1029 anr_traces_dir = dirname(anr_traces_file.c_str());
1030 }
1031 } else {
1032 is_global_trace_file = false;
1033 }
1034
1035 // We have neither configured a global trace file nor a trace directory,
1036 // there will be nothing to dump.
1037 if (anr_traces_file.empty() && anr_traces_dir.empty()) {
1038 printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
1039 return;
1040 }
1041
1042 if (is_global_trace_file) {
1043 AddGlobalAnrTraceFile(add_to_zip, anr_traces_file, anr_traces_dir);
1044 } else {
1045 AddAnrTraceDir(add_to_zip, anr_traces_dir);
1046 }
1047
1048 /* slow traces for slow operations */
1049 struct stat st;
1050 if (!anr_traces_dir.empty()) {
1051 int i = 0;
1052 while (true) {
1053 const std::string slow_trace_path =
1054 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
1055 if (stat(slow_trace_path.c_str(), &st)) {
1056 // No traces file at this index, done with the files.
1057 break;
1058 }
1059 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
1060 i++;
1061 }
1062 }
1063 }
1064
DumpBlockStatFiles()1065 static void DumpBlockStatFiles() {
1066 DurationReporter duration_reporter("DUMP BLOCK STAT");
1067
1068 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
1069
1070 if (dirptr == nullptr) {
1071 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1072 return;
1073 }
1074
1075 printf("------ DUMP BLOCK STAT ------\n\n");
1076 while (struct dirent *d = readdir(dirptr.get())) {
1077 if ((d->d_name[0] == '.')
1078 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1079 || (d->d_name[1] == '\0'))) {
1080 continue;
1081 }
1082 const std::string new_path =
1083 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1084 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1085 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1086 printf("\n");
1087 }
1088 return;
1089 }
1090
DumpPacketStats()1091 static void DumpPacketStats() {
1092 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
1093 DumpFile("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
1094 DumpFile("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
1095 DumpFile("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
1096 DumpFile("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
1097 }
1098
DumpIpAddrAndRules()1099 static void DumpIpAddrAndRules() {
1100 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
1101 RunCommand("NETWORK INTERFACES", {"ip", "link"});
1102 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1103 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1104 RunCommand("IP RULES", {"ip", "rule", "show"});
1105 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1106 }
1107
RunDumpsysTextByPriority(const std::string & title,int priority,std::chrono::milliseconds timeout,std::chrono::milliseconds service_timeout)1108 static void RunDumpsysTextByPriority(const std::string& title, int priority,
1109 std::chrono::milliseconds timeout,
1110 std::chrono::milliseconds service_timeout) {
1111 auto start = std::chrono::steady_clock::now();
1112 sp<android::IServiceManager> sm = defaultServiceManager();
1113 Dumpsys dumpsys(sm.get());
1114 Vector<String16> args;
1115 Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
1116 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1117 for (const String16& service : services) {
1118 std::string path(title);
1119 path.append(" - ").append(String8(service).c_str());
1120 DumpstateSectionReporter section_reporter(path, ds.listener_, ds.report_section_);
1121 size_t bytes_written = 0;
1122 status_t status = dumpsys.startDumpThread(service, args);
1123 if (status == OK) {
1124 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1125 std::chrono::duration<double> elapsed_seconds;
1126 status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
1127 /* as_proto = */ false, elapsed_seconds, bytes_written);
1128 section_reporter.setSize(bytes_written);
1129 dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
1130 bool dump_complete = (status == OK);
1131 dumpsys.stopDumpThread(dump_complete);
1132 }
1133 section_reporter.setStatus(status);
1134
1135 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1136 std::chrono::steady_clock::now() - start);
1137 if (elapsed_duration > timeout) {
1138 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1139 elapsed_duration.count());
1140 break;
1141 }
1142 }
1143 }
1144
RunDumpsysText(const std::string & title,int priority,std::chrono::milliseconds timeout,std::chrono::milliseconds service_timeout)1145 static void RunDumpsysText(const std::string& title, int priority,
1146 std::chrono::milliseconds timeout,
1147 std::chrono::milliseconds service_timeout) {
1148 DurationReporter duration_reporter(title);
1149 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1150 fsync(STDOUT_FILENO);
1151 RunDumpsysTextByPriority(title, priority, timeout, service_timeout);
1152 }
1153
1154 /* Dump all services registered with Normal or Default priority. */
RunDumpsysTextNormalPriority(const std::string & title,std::chrono::milliseconds timeout,std::chrono::milliseconds service_timeout)1155 static void RunDumpsysTextNormalPriority(const std::string& title,
1156 std::chrono::milliseconds timeout,
1157 std::chrono::milliseconds service_timeout) {
1158 DurationReporter duration_reporter(title);
1159 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1160 fsync(STDOUT_FILENO);
1161 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout,
1162 service_timeout);
1163 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1164 service_timeout);
1165 }
1166
RunDumpsysProto(const std::string & title,int priority,std::chrono::milliseconds timeout,std::chrono::milliseconds service_timeout)1167 static void RunDumpsysProto(const std::string& title, int priority,
1168 std::chrono::milliseconds timeout,
1169 std::chrono::milliseconds service_timeout) {
1170 if (!ds.IsZipping()) {
1171 MYLOGD("Not dumping %s because it's not a zipped bugreport\n", title.c_str());
1172 return;
1173 }
1174 sp<android::IServiceManager> sm = defaultServiceManager();
1175 Dumpsys dumpsys(sm.get());
1176 Vector<String16> args;
1177 Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
1178 DurationReporter duration_reporter(title);
1179
1180 auto start = std::chrono::steady_clock::now();
1181 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
1182 for (const String16& service : services) {
1183 std::string path(kProtoPath);
1184 path.append(String8(service).c_str());
1185 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
1186 path.append("_CRITICAL");
1187 } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
1188 path.append("_HIGH");
1189 }
1190 path.append(kProtoExt);
1191 DumpstateSectionReporter section_reporter(path, ds.listener_, ds.report_section_);
1192 status_t status = dumpsys.startDumpThread(service, args);
1193 if (status == OK) {
1194 status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
1195 bool dumpTerminated = (status == OK);
1196 dumpsys.stopDumpThread(dumpTerminated);
1197 }
1198 ZipWriter::FileEntry file_entry;
1199 ds.zip_writer_->GetLastEntry(&file_entry);
1200 section_reporter.setSize(file_entry.compressed_size);
1201 section_reporter.setStatus(status);
1202
1203 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1204 std::chrono::steady_clock::now() - start);
1205 if (elapsed_duration > timeout) {
1206 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1207 elapsed_duration.count());
1208 break;
1209 }
1210 }
1211 }
1212
1213 // Runs dumpsys on services that must dump first and and will take less than 100ms to dump.
RunDumpsysCritical()1214 static void RunDumpsysCritical() {
1215 RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1216 /* timeout= */ 5s, /* service_timeout= */ 500ms);
1217 RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1218 /* timeout= */ 5s, /* service_timeout= */ 500ms);
1219 }
1220
1221 // Runs dumpsys on services that must dump first but can take up to 250ms to dump.
RunDumpsysHigh()1222 static void RunDumpsysHigh() {
1223 // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
1224 // high priority. Reduce timeout once they are able to dump in a shorter time or
1225 // moved to a parallel task.
1226 RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1227 /* timeout= */ 90s, /* service_timeout= */ 30s);
1228 RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1229 /* timeout= */ 5s, /* service_timeout= */ 1s);
1230 }
1231
1232 // Runs dumpsys on services that must dump but can take up to 10s to dump.
RunDumpsysNormal()1233 static void RunDumpsysNormal() {
1234 RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
1235 RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1236 /* timeout= */ 90s, /* service_timeout= */ 10s);
1237 }
1238
DumpHals()1239 static void DumpHals() {
1240 using android::hidl::manager::V1_0::IServiceManager;
1241 using android::hardware::defaultServiceManager;
1242
1243 sp<IServiceManager> sm = defaultServiceManager();
1244 if (sm == nullptr) {
1245 MYLOGE("Could not retrieve hwservicemanager to dump hals.\n");
1246 return;
1247 }
1248
1249 auto ret = sm->list([&](const auto& interfaces) {
1250 for (const std::string& interface : interfaces) {
1251 std::string cleanName = interface;
1252 std::replace_if(cleanName.begin(),
1253 cleanName.end(),
1254 [](char c) {
1255 return !isalnum(c) &&
1256 std::string("@-_:.").find(c) == std::string::npos;
1257 }, '_');
1258 const std::string path = kDumpstateBoardPath + "lshal_debug_" + cleanName;
1259
1260 {
1261 auto fd = android::base::unique_fd(
1262 TEMP_FAILURE_RETRY(open(path.c_str(),
1263 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1264 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1265 if (fd < 0) {
1266 MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str());
1267 continue;
1268 }
1269 RunCommandToFd(fd,
1270 "",
1271 {"lshal", "debug", "-E", interface},
1272 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1273
1274 bool empty = 0 == lseek(fd, 0, SEEK_END);
1275 if (!empty) {
1276 ds.AddZipEntry("lshal-debug/" + cleanName + ".txt", path);
1277 }
1278 }
1279
1280 unlink(path.c_str());
1281 }
1282 });
1283
1284 if (!ret.isOk()) {
1285 MYLOGE("Could not list hals from hwservicemanager.\n");
1286 }
1287 }
1288
dumpstate()1289 static void dumpstate() {
1290 DurationReporter duration_reporter("DUMPSTATE");
1291
1292 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
1293 RunCommand("UPTIME", {"uptime"});
1294 DumpBlockStatFiles();
1295 dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
1296 DumpFile("MEMORY INFO", "/proc/meminfo");
1297 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
1298 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
1299 RunCommand("PROCRANK", {"procrank"}, AS_ROOT_20);
1300 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1301 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1302 DumpFile("SLAB INFO", "/proc/slabinfo");
1303 DumpFile("ZONEINFO", "/proc/zoneinfo");
1304 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1305 DumpFile("BUDDYINFO", "/proc/buddyinfo");
1306 DumpFile("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
1307
1308 DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources");
1309 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
1310 DumpFile("KERNEL SYNC", "/d/sync");
1311
1312 RunCommand("PROCESSES AND THREADS",
1313 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
1314 RunCommand("LIBRANK", {"librank"}, CommandOptions::AS_ROOT);
1315
1316 if (ds.IsZipping()) {
1317 RunCommand("HARDWARE HALS", {"lshal"}, CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1318 DumpHals();
1319 } else {
1320 RunCommand("HARDWARE HALS", {"lshal", "--debug"}, CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
1321 }
1322
1323 RunCommand("PRINTENV", {"printenv"});
1324 RunCommand("NETSTAT", {"netstat", "-nW"});
1325 struct stat s;
1326 if (stat("/proc/modules", &s) != 0) {
1327 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1328 } else {
1329 RunCommand("LSMOD", {"lsmod"});
1330 }
1331
1332 if (__android_logger_property_get_bool(
1333 "ro.logd.kernel", BOOL_DEFAULT_TRUE | BOOL_DEFAULT_FLAG_ENG | BOOL_DEFAULT_FLAG_SVELTE)) {
1334 DoKernelLogcat();
1335 } else {
1336 do_dmesg();
1337 }
1338
1339 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
1340 for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES");
1341 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
1342 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
1343
1344 /* Dump Bluetooth HCI logs */
1345 ds.AddDir("/data/misc/bluetooth/logs", true);
1346
1347 if (!ds.do_early_screenshot_) {
1348 MYLOGI("taking late screenshot\n");
1349 ds.TakeScreenshot();
1350 }
1351
1352 DoLogcat();
1353
1354 AddAnrTraceFiles();
1355
1356 // NOTE: tombstones are always added as separate entries in the zip archive
1357 // and are not interspersed with the main report.
1358 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
1359 "TOMBSTONE", true /* add_to_zip */);
1360 if (!tombstones_dumped) {
1361 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
1362 }
1363
1364 DumpPacketStats();
1365
1366 DoKmsg();
1367
1368 DumpIpAddrAndRules();
1369
1370 dump_route_tables();
1371
1372 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1373 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1374 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
1375
1376 RunDumpsysHigh();
1377
1378 RunCommand("SYSTEM PROPERTIES", {"getprop"});
1379
1380 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
1381
1382 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
1383
1384 RunCommand("LAST RADIO LOG", {"parse_radio_log", "/proc/last_radio_log"});
1385
1386 /* Binder state is expensive to look at as it uses a lot of memory. */
1387 DumpFile("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
1388 DumpFile("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
1389 DumpFile("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
1390 DumpFile("BINDER STATS", "/sys/kernel/debug/binder/stats");
1391 DumpFile("BINDER STATE", "/sys/kernel/debug/binder/state");
1392
1393 /* Add window and surface trace files. */
1394 if (!PropertiesHelper::IsUserBuild()) {
1395 ds.AddDir(WMTRACE_DATA_DIR, false);
1396 }
1397
1398 ds.DumpstateBoard();
1399
1400 /* Migrate the ril_dumpstate to a device specific dumpstate? */
1401 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1402 if (rilDumpstateTimeout > 0) {
1403 // su does not exist on user builds, so try running without it.
1404 // This way any implementations of vril-dump that do not require
1405 // root can run on user builds.
1406 CommandOptions::CommandOptionsBuilder options =
1407 CommandOptions::WithTimeout(rilDumpstateTimeout);
1408 if (!PropertiesHelper::IsUserBuild()) {
1409 options.AsRoot();
1410 }
1411 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
1412 }
1413
1414 printf("========================================================\n");
1415 printf("== Android Framework Services\n");
1416 printf("========================================================\n");
1417
1418 RunDumpsysNormal();
1419
1420 printf("========================================================\n");
1421 printf("== Checkins\n");
1422 printf("========================================================\n");
1423
1424 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1425 RunDumpsys("CHECKIN MEMINFO", {"meminfo", "--checkin"});
1426 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"});
1427 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"});
1428 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"});
1429 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"});
1430
1431 printf("========================================================\n");
1432 printf("== Running Application Activities\n");
1433 printf("========================================================\n");
1434
1435 // The following dumpsys internally collects output from running apps, so it can take a long
1436 // time. So let's extend the timeout.
1437
1438 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1439
1440 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS);
1441
1442 printf("========================================================\n");
1443 printf("== Running Application Services (platform)\n");
1444 printf("========================================================\n");
1445
1446 RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform"},
1447 DUMPSYS_COMPONENTS_OPTIONS);
1448
1449 printf("========================================================\n");
1450 printf("== Running Application Services (non-platform)\n");
1451 printf("========================================================\n");
1452
1453 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1454 DUMPSYS_COMPONENTS_OPTIONS);
1455
1456 printf("========================================================\n");
1457 printf("== Running Application Providers (platform)\n");
1458 printf("========================================================\n");
1459
1460 RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
1461 DUMPSYS_COMPONENTS_OPTIONS);
1462
1463 printf("========================================================\n");
1464 printf("== Running Application Providers (non-platform)\n");
1465 printf("========================================================\n");
1466
1467 RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1468 DUMPSYS_COMPONENTS_OPTIONS);
1469
1470 printf("========================================================\n");
1471 printf("== Dropbox crashes\n");
1472 printf("========================================================\n");
1473
1474 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1475 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1476
1477 printf("========================================================\n");
1478 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1479 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1480 printf("========================================================\n");
1481 printf("== dumpstate: done (id %d)\n", ds.id_);
1482 printf("========================================================\n");
1483 }
1484
1485 // This method collects common dumpsys for telephony and wifi
DumpstateRadioCommon()1486 static void DumpstateRadioCommon() {
1487 DumpIpTablesAsRoot();
1488
1489 if (!DropRootUser()) {
1490 return;
1491 }
1492
1493 do_dmesg();
1494 DoLogcat();
1495 DumpPacketStats();
1496 DoKmsg();
1497 DumpIpAddrAndRules();
1498 dump_route_tables();
1499
1500 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
1501 CommandOptions::WithTimeout(10).Build());
1502 }
1503
1504 // This method collects dumpsys for telephony debugging only
DumpstateTelephonyOnly()1505 static void DumpstateTelephonyOnly() {
1506 DurationReporter duration_reporter("DUMPSTATE");
1507 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1508
1509 DumpstateRadioCommon();
1510
1511 RunCommand("SYSTEM PROPERTIES", {"getprop"});
1512
1513 printf("========================================================\n");
1514 printf("== Android Framework Services\n");
1515 printf("========================================================\n");
1516
1517 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1518 SEC_TO_MSEC(10));
1519 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
1520 SEC_TO_MSEC(10));
1521 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
1522 SEC_TO_MSEC(10));
1523 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
1524 SEC_TO_MSEC(10));
1525
1526 printf("========================================================\n");
1527 printf("== Running Application Services\n");
1528 printf("========================================================\n");
1529
1530 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
1531
1532 printf("========================================================\n");
1533 printf("== Running Application Services (non-platform)\n");
1534 printf("========================================================\n");
1535
1536 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1537 DUMPSYS_COMPONENTS_OPTIONS);
1538
1539 printf("========================================================\n");
1540 printf("== dumpstate: done (id %d)\n", ds.id_);
1541 printf("========================================================\n");
1542 }
1543
1544 // This method collects dumpsys for wifi debugging only
DumpstateWifiOnly()1545 static void DumpstateWifiOnly() {
1546 DurationReporter duration_reporter("DUMPSTATE");
1547
1548 DumpstateRadioCommon();
1549
1550 printf("========================================================\n");
1551 printf("== Android Framework Services\n");
1552 printf("========================================================\n");
1553
1554 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1555 SEC_TO_MSEC(10));
1556 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
1557 SEC_TO_MSEC(10));
1558
1559 printf("========================================================\n");
1560 printf("== dumpstate: done (id %d)\n", ds.id_);
1561 printf("========================================================\n");
1562 }
1563
DumpstateBoard()1564 void Dumpstate::DumpstateBoard() {
1565 DurationReporter duration_reporter("dumpstate_board()");
1566 printf("========================================================\n");
1567 printf("== Board\n");
1568 printf("========================================================\n");
1569
1570 if (!IsZipping()) {
1571 MYLOGD("Not dumping board info because it's not a zipped bugreport\n");
1572 return;
1573 }
1574
1575 std::vector<std::string> paths;
1576 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
1577 for (int i = 0; i < NUM_OF_DUMPS; i++) {
1578 paths.emplace_back(kDumpstateBoardPath + kDumpstateBoardFiles[i]);
1579 remover.emplace_back(android::base::make_scope_guard(std::bind(
1580 [](std::string path) {
1581 if (remove(path.c_str()) != 0 && errno != ENOENT) {
1582 MYLOGE("Could not remove(%s): %s\n", path.c_str(), strerror(errno));
1583 }
1584 },
1585 paths[i])));
1586 }
1587
1588 sp<IDumpstateDevice> dumpstate_device(IDumpstateDevice::getService());
1589 if (dumpstate_device == nullptr) {
1590 MYLOGE("No IDumpstateDevice implementation\n");
1591 return;
1592 }
1593
1594 using ScopedNativeHandle =
1595 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
1596 ScopedNativeHandle handle(native_handle_create(static_cast<int>(paths.size()), 0),
1597 [](native_handle_t* handle) {
1598 native_handle_close(handle);
1599 native_handle_delete(handle);
1600 });
1601 if (handle == nullptr) {
1602 MYLOGE("Could not create native_handle\n");
1603 return;
1604 }
1605
1606 for (size_t i = 0; i < paths.size(); i++) {
1607 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
1608
1609 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
1610 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1611 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1612 if (fd < 0) {
1613 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
1614 return;
1615 }
1616 handle.get()->data[i] = fd.release();
1617 }
1618
1619 // Given that bugreport is required to diagnose failures, it's better to
1620 // set an arbitrary amount of timeout for IDumpstateDevice than to block the
1621 // rest of bugreport. In the timeout case, we will kill dumpstate board HAL
1622 // and grab whatever dumped
1623 std::packaged_task<bool()>
1624 dumpstate_task([paths, dumpstate_device, &handle]() -> bool {
1625 android::hardware::Return<void> status = dumpstate_device->dumpstateBoard(handle.get());
1626 if (!status.isOk()) {
1627 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
1628 return false;
1629 }
1630 return true;
1631 });
1632
1633 auto result = dumpstate_task.get_future();
1634 std::thread(std::move(dumpstate_task)).detach();
1635
1636 constexpr size_t timeout_sec = 30;
1637 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
1638 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate vendor HAL\n", timeout_sec);
1639 if (!android::base::SetProperty("ctl.interface_restart",
1640 android::base::StringPrintf("%s/default",
1641 IDumpstateDevice::descriptor))) {
1642 MYLOGE("Couldn't restart dumpstate HAL\n");
1643 }
1644 }
1645 // Wait some time for init to kill dumpstate vendor HAL
1646 constexpr size_t killing_timeout_sec = 10;
1647 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
1648 MYLOGE("killing dumpstateBoard timed out after %zus, continue and "
1649 "there might be racing in content\n", killing_timeout_sec);
1650 }
1651
1652 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
1653 for (size_t i = 0; i < paths.size(); i++) {
1654 struct stat s;
1655 if (fstat(handle.get()->data[i], &s) == -1) {
1656 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(),
1657 strerror(errno));
1658 file_sizes[i] = -1;
1659 continue;
1660 }
1661 file_sizes[i] = s.st_size;
1662 }
1663
1664 for (size_t i = 0; i < paths.size(); i++) {
1665 if (file_sizes[i] == -1) {
1666 continue;
1667 }
1668 if (file_sizes[i] == 0) {
1669 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
1670 continue;
1671 }
1672 AddZipEntry(kDumpstateBoardFiles[i], paths[i]);
1673 }
1674
1675 printf("*** See dumpstate-board.txt entry ***\n");
1676 }
1677
ShowUsageAndExit(int exitCode=1)1678 static void ShowUsageAndExit(int exitCode = 1) {
1679 fprintf(stderr,
1680 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file] [-d] [-p] "
1681 "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
1682 " -h: display this help message\n"
1683 " -b: play sound file instead of vibrate, at beginning of job\n"
1684 " -e: play sound file instead of vibrate, at end of job\n"
1685 " -o: write to file (instead of stdout)\n"
1686 " -d: append date to filename (requires -o)\n"
1687 " -p: capture screenshot to filename.png (requires -o)\n"
1688 " -z: generate zipped file (requires -o)\n"
1689 " -s: write output to control socket (for init)\n"
1690 " -S: write file location to control socket (for init; requires -o and -z)\n"
1691 " -q: disable vibrate\n"
1692 " -B: send broadcast when finished (requires -o)\n"
1693 " -P: send broadcast when started and update system properties on "
1694 "progress (requires -o and -B)\n"
1695 " -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
1696 "shouldn't be used with -P)\n"
1697 " -v: prints the dumpstate header and exit\n");
1698 exit(exitCode);
1699 }
1700
ExitOnInvalidArgs()1701 static void ExitOnInvalidArgs() {
1702 fprintf(stderr, "invalid combination of args\n");
1703 ShowUsageAndExit();
1704 }
1705
register_sig_handler()1706 static void register_sig_handler() {
1707 signal(SIGPIPE, SIG_IGN);
1708 }
1709
FinishZipFile()1710 bool Dumpstate::FinishZipFile() {
1711 std::string entry_name = base_name_ + "-" + name_ + ".txt";
1712 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
1713 tmp_path_.c_str());
1714 // Final timestamp
1715 char date[80];
1716 time_t the_real_now_please_stand_up = time(nullptr);
1717 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
1718 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
1719 the_real_now_please_stand_up - ds.now_);
1720
1721 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
1722 MYLOGE("Failed to add text entry to .zip file\n");
1723 return false;
1724 }
1725 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
1726 MYLOGE("Failed to add main_entry.txt to .zip file\n");
1727 return false;
1728 }
1729
1730 // Add log file (which contains stderr output) to zip...
1731 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
1732 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
1733 MYLOGE("Failed to add dumpstate log to .zip file\n");
1734 return false;
1735 }
1736 // ... and re-opens it for further logging.
1737 redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()));
1738 fprintf(stderr, "\n");
1739
1740 int32_t err = zip_writer_->Finish();
1741 if (err != 0) {
1742 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
1743 return false;
1744 }
1745
1746 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
1747 ds.zip_file.reset(nullptr);
1748
1749 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
1750 if (remove(tmp_path_.c_str()) != 0) {
1751 MYLOGE("Failed to remove temporary file (%s): %s\n", tmp_path_.c_str(), strerror(errno));
1752 }
1753
1754 return true;
1755 }
1756
SHA256_file_hash(const std::string & filepath)1757 static std::string SHA256_file_hash(const std::string& filepath) {
1758 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK
1759 | O_CLOEXEC | O_NOFOLLOW)));
1760 if (fd == -1) {
1761 MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
1762 return NULL;
1763 }
1764
1765 SHA256_CTX ctx;
1766 SHA256_Init(&ctx);
1767
1768 std::vector<uint8_t> buffer(65536);
1769 while (1) {
1770 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
1771 if (bytes_read == 0) {
1772 break;
1773 } else if (bytes_read == -1) {
1774 MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
1775 return NULL;
1776 }
1777
1778 SHA256_Update(&ctx, buffer.data(), bytes_read);
1779 }
1780
1781 uint8_t hash[SHA256_DIGEST_LENGTH];
1782 SHA256_Final(hash, &ctx);
1783
1784 char hash_buffer[SHA256_DIGEST_LENGTH * 2 + 1];
1785 for(size_t i = 0; i < SHA256_DIGEST_LENGTH; i++) {
1786 sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
1787 }
1788 hash_buffer[sizeof(hash_buffer) - 1] = 0;
1789 return std::string(hash_buffer);
1790 }
1791
SendBroadcast(const std::string & action,const std::vector<std::string> & args)1792 static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) {
1793 // clang-format off
1794 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0",
1795 "--receiver-foreground", "--receiver-include-background", "-a", action};
1796 // clang-format on
1797
1798 am.insert(am.end(), args.begin(), args.end());
1799
1800 RunCommand("", am,
1801 CommandOptions::WithTimeout(20)
1802 .Log("Sending broadcast: '%s'\n")
1803 .Always()
1804 .DropRoot()
1805 .RedirectStderr()
1806 .Build());
1807 }
1808
Vibrate(int duration_ms)1809 static void Vibrate(int duration_ms) {
1810 // clang-format off
1811 RunCommand("", {"cmd", "vibrator", "vibrate", std::to_string(duration_ms), "dumpstate"},
1812 CommandOptions::WithTimeout(10)
1813 .Log("Vibrate: '%s'\n")
1814 .Always()
1815 .Build());
1816 // clang-format on
1817 }
1818
1819 /** Main entry point for dumpstate. */
run_main(int argc,char * argv[])1820 int run_main(int argc, char* argv[]) {
1821 int do_add_date = 0;
1822 int do_zip_file = 0;
1823 int do_vibrate = 1;
1824 char* use_outfile = 0;
1825 int use_socket = 0;
1826 int use_control_socket = 0;
1827 int do_fb = 0;
1828 int do_broadcast = 0;
1829 int is_remote_mode = 0;
1830 bool show_header_only = false;
1831 bool do_start_service = false;
1832 bool telephony_only = false;
1833 bool wifi_only = false;
1834 int dup_stdout_fd;
1835 int dup_stderr_fd;
1836
1837 /* set as high priority, and protect from OOM killer */
1838 setpriority(PRIO_PROCESS, 0, -20);
1839
1840 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
1841 if (oom_adj) {
1842 fputs("-1000", oom_adj);
1843 fclose(oom_adj);
1844 } else {
1845 /* fallback to kernels <= 2.6.35 */
1846 oom_adj = fopen("/proc/self/oom_adj", "we");
1847 if (oom_adj) {
1848 fputs("-17", oom_adj);
1849 fclose(oom_adj);
1850 }
1851 }
1852
1853 /* parse arguments */
1854 int c;
1855 while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
1856 switch (c) {
1857 // clang-format off
1858 case 'd': do_add_date = 1; break;
1859 case 'z': do_zip_file = 1; break;
1860 case 'o': use_outfile = optarg; break;
1861 case 's': use_socket = 1; break;
1862 case 'S': use_control_socket = 1; break;
1863 case 'v': show_header_only = true; break;
1864 case 'q': do_vibrate = 0; break;
1865 case 'p': do_fb = 1; break;
1866 case 'P': ds.update_progress_ = true; break;
1867 case 'R': is_remote_mode = 1; break;
1868 case 'B': do_broadcast = 1; break;
1869 case 'V': break; // compatibility no-op
1870 case 'h':
1871 ShowUsageAndExit(0);
1872 break;
1873 default:
1874 fprintf(stderr, "Invalid option: %c\n", c);
1875 ShowUsageAndExit();
1876 // clang-format on
1877 }
1878 }
1879
1880 // TODO: use helper function to convert argv into a string
1881 for (int i = 0; i < argc; i++) {
1882 ds.args_ += argv[i];
1883 if (i < argc - 1) {
1884 ds.args_ += " ";
1885 }
1886 }
1887
1888 ds.extra_options_ = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
1889 if (!ds.extra_options_.empty()) {
1890 // Framework uses a system property to override some command-line args.
1891 // Currently, it contains the type of the requested bugreport.
1892 if (ds.extra_options_ == "bugreportplus") {
1893 // Currently, the dumpstate binder is only used by Shell to update progress.
1894 do_start_service = true;
1895 ds.update_progress_ = true;
1896 do_fb = 0;
1897 } else if (ds.extra_options_ == "bugreportremote") {
1898 do_vibrate = 0;
1899 is_remote_mode = 1;
1900 do_fb = 0;
1901 } else if (ds.extra_options_ == "bugreportwear") {
1902 do_start_service = true;
1903 ds.update_progress_ = true;
1904 do_zip_file = 1;
1905 } else if (ds.extra_options_ == "bugreporttelephony") {
1906 telephony_only = true;
1907 } else if (ds.extra_options_ == "bugreportwifi") {
1908 wifi_only = true;
1909 do_zip_file = 1;
1910 } else {
1911 MYLOGE("Unknown extra option: %s\n", ds.extra_options_.c_str());
1912 }
1913 // Reset the property
1914 android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, "");
1915 }
1916
1917 ds.notification_title = android::base::GetProperty(PROPERTY_EXTRA_TITLE, "");
1918 if (!ds.notification_title.empty()) {
1919 // Reset the property
1920 android::base::SetProperty(PROPERTY_EXTRA_TITLE, "");
1921
1922 ds.notification_description = android::base::GetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
1923 if (!ds.notification_description.empty()) {
1924 // Reset the property
1925 android::base::SetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
1926 }
1927 MYLOGD("notification (title: %s, description: %s)\n",
1928 ds.notification_title.c_str(), ds.notification_description.c_str());
1929 }
1930
1931 if ((do_zip_file || do_add_date || ds.update_progress_ || do_broadcast) && !use_outfile) {
1932 ExitOnInvalidArgs();
1933 }
1934
1935 if (use_control_socket && !do_zip_file) {
1936 ExitOnInvalidArgs();
1937 }
1938
1939 if (ds.update_progress_ && !do_broadcast) {
1940 ExitOnInvalidArgs();
1941 }
1942
1943 if (is_remote_mode && (ds.update_progress_ || !do_broadcast || !do_zip_file || !do_add_date)) {
1944 ExitOnInvalidArgs();
1945 }
1946
1947 if (ds.version_ == VERSION_DEFAULT) {
1948 ds.version_ = VERSION_CURRENT;
1949 }
1950
1951 if (ds.version_ != VERSION_CURRENT && ds.version_ != VERSION_SPLIT_ANR) {
1952 MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s')\n",
1953 ds.version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
1954 VERSION_SPLIT_ANR.c_str());
1955 exit(1);
1956 }
1957
1958 if (show_header_only) {
1959 ds.PrintHeader();
1960 exit(0);
1961 }
1962
1963 /* redirect output if needed */
1964 bool is_redirecting = !use_socket && use_outfile;
1965
1966 // TODO: temporarily set progress until it's part of the Dumpstate constructor
1967 std::string stats_path =
1968 is_redirecting ? android::base::StringPrintf("%s/dumpstate-stats.txt", dirname(use_outfile))
1969 : "";
1970 ds.progress_.reset(new Progress(stats_path));
1971
1972 /* gets the sequential id */
1973 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
1974 ds.id_ = ++last_id;
1975 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
1976
1977 MYLOGI("begin\n");
1978
1979 register_sig_handler();
1980
1981 if (do_start_service) {
1982 MYLOGI("Starting 'dumpstate' service\n");
1983 android::status_t ret;
1984 if ((ret = android::os::DumpstateService::Start()) != android::OK) {
1985 MYLOGE("Unable to start DumpstateService: %d\n", ret);
1986 }
1987 }
1988
1989 if (PropertiesHelper::IsDryRun()) {
1990 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
1991 }
1992
1993 MYLOGI("dumpstate info: id=%d, args='%s', extra_options= %s)\n", ds.id_, ds.args_.c_str(),
1994 ds.extra_options_.c_str());
1995
1996 MYLOGI("bugreport format version: %s\n", ds.version_.c_str());
1997
1998 ds.do_early_screenshot_ = ds.update_progress_;
1999
2000 // If we are going to use a socket, do it as early as possible
2001 // to avoid timeouts from bugreport.
2002 if (use_socket) {
2003 redirect_to_socket(stdout, "dumpstate");
2004 }
2005
2006 if (use_control_socket) {
2007 MYLOGD("Opening control socket\n");
2008 ds.control_socket_fd_ = open_socket("dumpstate");
2009 ds.update_progress_ = 1;
2010 }
2011
2012 if (is_redirecting) {
2013 ds.bugreport_dir_ = dirname(use_outfile);
2014 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2015 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
2016 ds.base_name_ = android::base::StringPrintf("%s-%s-%s", basename(use_outfile),
2017 device_name.c_str(), build_id.c_str());
2018 if (do_add_date) {
2019 char date[80];
2020 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2021 ds.name_ = date;
2022 } else {
2023 ds.name_ = "undated";
2024 }
2025
2026 if (telephony_only) {
2027 ds.base_name_ += "-telephony";
2028 } else if (wifi_only) {
2029 ds.base_name_ += "-wifi";
2030 }
2031
2032 if (do_fb) {
2033 ds.screenshot_path_ = ds.GetPath(".png");
2034 }
2035 ds.tmp_path_ = ds.GetPath(".tmp");
2036 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2037
2038 MYLOGD(
2039 "Bugreport dir: %s\n"
2040 "Base name: %s\n"
2041 "Suffix: %s\n"
2042 "Log path: %s\n"
2043 "Temporary path: %s\n"
2044 "Screenshot path: %s\n",
2045 ds.bugreport_dir_.c_str(), ds.base_name_.c_str(), ds.name_.c_str(),
2046 ds.log_path_.c_str(), ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
2047
2048 if (do_zip_file) {
2049 ds.path_ = ds.GetPath(".zip");
2050 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2051 create_parent_dirs(ds.path_.c_str());
2052 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2053 if (ds.zip_file == nullptr) {
2054 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2055 do_zip_file = 0;
2056 } else {
2057 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2058 }
2059 ds.AddTextZipEntry("version.txt", ds.version_);
2060 }
2061
2062 if (ds.update_progress_) {
2063 if (do_broadcast) {
2064 // clang-format off
2065
2066 std::vector<std::string> am_args = {
2067 "--receiver-permission", "android.permission.DUMP",
2068 "--es", "android.intent.extra.NAME", ds.name_,
2069 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
2070 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
2071 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
2072 };
2073 // clang-format on
2074 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
2075 }
2076 if (use_control_socket) {
2077 dprintf(ds.control_socket_fd_, "BEGIN:%s\n", ds.path_.c_str());
2078 }
2079 }
2080 }
2081
2082 /* read /proc/cmdline before dropping root */
2083 FILE *cmdline = fopen("/proc/cmdline", "re");
2084 if (cmdline) {
2085 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
2086 fclose(cmdline);
2087 }
2088
2089 if (do_vibrate) {
2090 Vibrate(150);
2091 }
2092
2093 if (do_fb && ds.do_early_screenshot_) {
2094 if (ds.screenshot_path_.empty()) {
2095 // should not have happened
2096 MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
2097 } else {
2098 MYLOGI("taking early screenshot\n");
2099 ds.TakeScreenshot();
2100 }
2101 }
2102
2103 if (do_zip_file) {
2104 if (chown(ds.path_.c_str(), AID_SHELL, AID_SHELL)) {
2105 MYLOGE("Unable to change ownership of zip file %s: %s\n", ds.path_.c_str(),
2106 strerror(errno));
2107 }
2108 }
2109
2110 if (is_redirecting) {
2111 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
2112 redirect_to_file(stderr, const_cast<char*>(ds.log_path_.c_str()));
2113 if (chown(ds.log_path_.c_str(), AID_SHELL, AID_SHELL)) {
2114 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n",
2115 ds.log_path_.c_str(), strerror(errno));
2116 }
2117 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
2118 /* TODO: rather than generating a text file now and zipping it later,
2119 it would be more efficient to redirect stdout to the zip entry
2120 directly, but the libziparchive doesn't support that option yet. */
2121 redirect_to_file(stdout, const_cast<char*>(ds.tmp_path_.c_str()));
2122 if (chown(ds.tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
2123 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
2124 ds.tmp_path_.c_str(), strerror(errno));
2125 }
2126 }
2127
2128 // Don't buffer stdout
2129 setvbuf(stdout, nullptr, _IONBF, 0);
2130
2131 // NOTE: there should be no stdout output until now, otherwise it would break the header.
2132 // In particular, DurationReport objects should be created passing 'title, NULL', so their
2133 // duration is logged into MYLOG instead.
2134 ds.PrintHeader();
2135
2136 if (telephony_only) {
2137 DumpstateTelephonyOnly();
2138 ds.DumpstateBoard();
2139 } else if (wifi_only) {
2140 DumpstateWifiOnly();
2141 } else {
2142 // Dumps systrace right away, otherwise it will be filled with unnecessary events.
2143 // First try to dump anrd trace if the daemon is running. Otherwise, dump
2144 // the raw trace.
2145 if (!dump_anrd_trace()) {
2146 dump_systrace();
2147 }
2148
2149 // Invoking the following dumpsys calls before dump_traces() to try and
2150 // keep the system stats as close to its initial state as possible.
2151 RunDumpsysCritical();
2152
2153 // TODO: Drop root user and move into dumpstate() once b/28633932 is fixed.
2154 dump_raft();
2155
2156 /* collect stack traces from Dalvik and native processes (needs root) */
2157 dump_traces_path = dump_traces();
2158
2159 /* Run some operations that require root. */
2160 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping());
2161 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping());
2162
2163 ds.AddDir(RECOVERY_DIR, true);
2164 ds.AddDir(RECOVERY_DATA_DIR, true);
2165 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
2166 ds.AddDir(LOGPERSIST_DATA_DIR, false);
2167 if (!PropertiesHelper::IsUserBuild()) {
2168 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
2169 ds.AddDir(PROFILE_DATA_DIR_REF, true);
2170 }
2171 add_mountinfo();
2172 DumpIpTablesAsRoot();
2173
2174 // Capture any IPSec policies in play. No keys are exposed here.
2175 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"},
2176 CommandOptions::WithTimeout(10).Build());
2177
2178 // Run ss as root so we can see socket marks.
2179 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"},
2180 CommandOptions::WithTimeout(10).Build());
2181
2182 // Run iotop as root to show top 100 IO threads
2183 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
2184
2185 if (!DropRootUser()) {
2186 return -1;
2187 }
2188
2189 dumpstate();
2190 }
2191
2192 /* close output if needed */
2193 if (is_redirecting) {
2194 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
2195 }
2196
2197 /* rename or zip the (now complete) .tmp file to its final location */
2198 if (use_outfile) {
2199
2200 /* check if user changed the suffix using system properties */
2201 std::string name = android::base::GetProperty(
2202 android::base::StringPrintf("dumpstate.%d.name", ds.pid_), "");
2203 bool change_suffix= false;
2204 if (!name.empty()) {
2205 /* must whitelist which characters are allowed, otherwise it could cross directories */
2206 std::regex valid_regex("^[-_a-zA-Z0-9]+$");
2207 if (std::regex_match(name.c_str(), valid_regex)) {
2208 change_suffix = true;
2209 } else {
2210 MYLOGE("invalid suffix provided by user: %s\n", name.c_str());
2211 }
2212 }
2213 if (change_suffix) {
2214 MYLOGI("changing suffix from %s to %s\n", ds.name_.c_str(), name.c_str());
2215 ds.name_ = name;
2216 if (!ds.screenshot_path_.empty()) {
2217 std::string new_screenshot_path = ds.GetPath(".png");
2218 if (rename(ds.screenshot_path_.c_str(), new_screenshot_path.c_str())) {
2219 MYLOGE("rename(%s, %s): %s\n", ds.screenshot_path_.c_str(),
2220 new_screenshot_path.c_str(), strerror(errno));
2221 } else {
2222 ds.screenshot_path_ = new_screenshot_path;
2223 }
2224 }
2225 }
2226
2227 bool do_text_file = true;
2228 if (do_zip_file) {
2229 if (!ds.FinishZipFile()) {
2230 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
2231 do_text_file = true;
2232 } else {
2233 do_text_file = false;
2234 // Since zip file is already created, it needs to be renamed.
2235 std::string new_path = ds.GetPath(".zip");
2236 if (ds.path_ != new_path) {
2237 MYLOGD("Renaming zip file from %s to %s\n", ds.path_.c_str(), new_path.c_str());
2238 if (rename(ds.path_.c_str(), new_path.c_str())) {
2239 MYLOGE("rename(%s, %s): %s\n", ds.path_.c_str(), new_path.c_str(),
2240 strerror(errno));
2241 } else {
2242 ds.path_ = new_path;
2243 }
2244 }
2245 }
2246 }
2247 if (do_text_file) {
2248 ds.path_ = ds.GetPath(".txt");
2249 MYLOGD("Generating .txt bugreport at %s from %s\n", ds.path_.c_str(),
2250 ds.tmp_path_.c_str());
2251 if (rename(ds.tmp_path_.c_str(), ds.path_.c_str())) {
2252 MYLOGE("rename(%s, %s): %s\n", ds.tmp_path_.c_str(), ds.path_.c_str(),
2253 strerror(errno));
2254 ds.path_.clear();
2255 }
2256 }
2257 if (use_control_socket) {
2258 if (do_text_file) {
2259 dprintf(ds.control_socket_fd_,
2260 "FAIL:could not create zip file, check %s "
2261 "for more details\n",
2262 ds.log_path_.c_str());
2263 } else {
2264 dprintf(ds.control_socket_fd_, "OK:%s\n", ds.path_.c_str());
2265 }
2266 }
2267 }
2268
2269 /* vibrate a few but shortly times to let user know it's finished */
2270 if (do_vibrate) {
2271 for (int i = 0; i < 3; i++) {
2272 Vibrate(75);
2273 usleep((75 + 50) * 1000);
2274 }
2275 }
2276
2277 /* tell activity manager we're done */
2278 if (do_broadcast) {
2279 if (!ds.path_.empty()) {
2280 MYLOGI("Final bugreport path: %s\n", ds.path_.c_str());
2281 // clang-format off
2282
2283 std::vector<std::string> am_args = {
2284 "--receiver-permission", "android.permission.DUMP",
2285 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
2286 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
2287 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
2288 "--es", "android.intent.extra.BUGREPORT", ds.path_,
2289 "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_
2290 };
2291 // clang-format on
2292 if (do_fb) {
2293 am_args.push_back("--es");
2294 am_args.push_back("android.intent.extra.SCREENSHOT");
2295 am_args.push_back(ds.screenshot_path_);
2296 }
2297 if (!ds.notification_title.empty()) {
2298 am_args.push_back("--es");
2299 am_args.push_back("android.intent.extra.TITLE");
2300 am_args.push_back(ds.notification_title);
2301 if (!ds.notification_description.empty()) {
2302 am_args.push_back("--es");
2303 am_args.push_back("android.intent.extra.DESCRIPTION");
2304 am_args.push_back(ds.notification_description);
2305 }
2306 }
2307 if (is_remote_mode) {
2308 am_args.push_back("--es");
2309 am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
2310 am_args.push_back(SHA256_file_hash(ds.path_));
2311 SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED",
2312 am_args);
2313 } else {
2314 SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args);
2315 }
2316 } else {
2317 MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
2318 }
2319 }
2320
2321 MYLOGD("Final progress: %d/%d (estimated %d)\n", ds.progress_->Get(), ds.progress_->GetMax(),
2322 ds.progress_->GetInitialMax());
2323 ds.progress_->Save();
2324 MYLOGI("done (id %d)\n", ds.id_);
2325
2326 if (is_redirecting) {
2327 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
2328 }
2329
2330 if (use_control_socket && ds.control_socket_fd_ != -1) {
2331 MYLOGD("Closing control socket\n");
2332 close(ds.control_socket_fd_);
2333 }
2334
2335 ds.tombstone_data_.clear();
2336 ds.anr_data_.clear();
2337
2338 return 0;
2339 }
2340