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 <inttypes.h>
23 #include <libgen.h>
24 #include <limits.h>
25 #include <stdbool.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <sys/poll.h>
30 #include <sys/prctl.h>
31 #include <sys/resource.h>
32 #include <sys/stat.h>
33 #include <sys/time.h>
34 #include <sys/wait.h>
35 #include <unistd.h>
36
37 #include <chrono>
38 #include <fstream>
39 #include <functional>
40 #include <future>
41 #include <memory>
42 #include <regex>
43 #include <set>
44 #include <string>
45 #include <utility>
46 #include <vector>
47
48 #include <android-base/file.h>
49 #include <android-base/properties.h>
50 #include <android-base/scopeguard.h>
51 #include <android-base/stringprintf.h>
52 #include <android-base/strings.h>
53 #include <android-base/unique_fd.h>
54 #include <android/content/pm/IPackageManagerNative.h>
55 #include <android/hardware/dumpstate/1.0/IDumpstateDevice.h>
56 #include <android/hidl/manager/1.0/IServiceManager.h>
57 #include <android/os/IIncidentCompanion.h>
58 #include <binder/IServiceManager.h>
59 #include <cutils/native_handle.h>
60 #include <cutils/properties.h>
61 #include <debuggerd/client.h>
62 #include <dumpsys.h>
63 #include <dumputils/dump_utils.h>
64 #include <hidl/ServiceManagement.h>
65 #include <openssl/sha.h>
66 #include <private/android_filesystem_config.h>
67 #include <private/android_logger.h>
68 #include <serviceutils/PriorityDumper.h>
69 #include <utils/StrongPointer.h>
70 #include "DumpstateInternal.h"
71 #include "DumpstateSectionReporter.h"
72 #include "DumpstateService.h"
73 #include "dumpstate.h"
74
75 using ::android::hardware::dumpstate::V1_0::IDumpstateDevice;
76 using ::std::literals::chrono_literals::operator""ms;
77 using ::std::literals::chrono_literals::operator""s;
78
79 // TODO: remove once moved to namespace
80 using android::defaultServiceManager;
81 using android::Dumpsys;
82 using android::INVALID_OPERATION;
83 using android::IServiceManager;
84 using android::OK;
85 using android::sp;
86 using android::status_t;
87 using android::String16;
88 using android::String8;
89 using android::TIMED_OUT;
90 using android::UNKNOWN_ERROR;
91 using android::Vector;
92 using android::base::StringPrintf;
93 using android::os::IDumpstateListener;
94 using android::os::dumpstate::CommandOptions;
95 using android::os::dumpstate::DumpFileToFd;
96 using android::os::dumpstate::DumpstateSectionReporter;
97 using android::os::dumpstate::GetPidByName;
98 using android::os::dumpstate::PropertiesHelper;
99
100 typedef Dumpstate::ConsentCallback::ConsentResult UserConsentResult;
101
102 /* read before root is shed */
103 static char cmdline_buf[16384] = "(unknown)";
104 static const char *dump_traces_path = nullptr;
105 static const uint64_t USER_CONSENT_TIMEOUT_MS = 30 * 1000;
106
107 // TODO: variables and functions below should be part of dumpstate object
108
109 static std::set<std::string> mount_points;
110 void add_mountinfo();
111
112 #define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
113 #define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
114 #define BLK_DEV_SYS_DIR "/sys/block"
115
116 #define RECOVERY_DIR "/cache/recovery"
117 #define RECOVERY_DATA_DIR "/data/misc/recovery"
118 #define UPDATE_ENGINE_LOG_DIR "/data/misc/update_engine_log"
119 #define LOGPERSIST_DATA_DIR "/data/misc/logd"
120 #define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
121 #define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
122 #define XFRM_STAT_PROC_FILE "/proc/net/xfrm_stat"
123 #define WLUTIL "/vendor/xbin/wlutil"
124 #define WMTRACE_DATA_DIR "/data/misc/wmtrace"
125
126 // TODO(narayan): Since this information has to be kept in sync
127 // with tombstoned, we should just put it in a common header.
128 //
129 // File: system/core/debuggerd/tombstoned/tombstoned.cpp
130 static const std::string TOMBSTONE_DIR = "/data/tombstones/";
131 static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
132 static const std::string ANR_DIR = "/data/anr/";
133 static const std::string ANR_FILE_PREFIX = "anr_";
134
135 // TODO: temporary variables and functions used during C++ refactoring
136 static Dumpstate& ds = Dumpstate::GetInstance();
137
138 #define RETURN_IF_USER_DENIED_CONSENT() \
139 if (ds.IsUserConsentDenied()) { \
140 MYLOGE("Returning early as user denied consent to share bugreport with calling app."); \
141 return Dumpstate::RunStatus::USER_CONSENT_DENIED; \
142 }
143
144 // Runs func_ptr, but checks user consent before and after running it. Returns USER_CONSENT_DENIED
145 // if consent is found to be denied.
146 #define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(func_ptr, ...) \
147 RETURN_IF_USER_DENIED_CONSENT(); \
148 func_ptr(__VA_ARGS__); \
149 RETURN_IF_USER_DENIED_CONSENT();
150
151 namespace android {
152 namespace os {
153 namespace {
154
Open(std::string path,int flags,mode_t mode=0)155 static int Open(std::string path, int flags, mode_t mode = 0) {
156 int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
157 if (fd == -1) {
158 MYLOGE("open(%s, %s)\n", path.c_str(), strerror(errno));
159 }
160 return fd;
161 }
162
163
OpenForRead(std::string path)164 static int OpenForRead(std::string path) {
165 return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
166 }
167
CopyFile(int in_fd,int out_fd)168 bool CopyFile(int in_fd, int out_fd) {
169 char buf[4096];
170 ssize_t byte_count;
171 while ((byte_count = TEMP_FAILURE_RETRY(read(in_fd, buf, sizeof(buf)))) > 0) {
172 if (!android::base::WriteFully(out_fd, buf, byte_count)) {
173 return false;
174 }
175 }
176 return (byte_count != -1);
177 }
178
CopyFileToFd(const std::string & input_file,int out_fd)179 static bool CopyFileToFd(const std::string& input_file, int out_fd) {
180 MYLOGD("Going to copy file (%s) to %d\n", input_file.c_str(), out_fd);
181
182 // Obtain a handle to the source file.
183 android::base::unique_fd in_fd(OpenForRead(input_file));
184 if (out_fd != -1 && in_fd.get() != -1) {
185 if (CopyFile(in_fd.get(), out_fd)) {
186 return true;
187 }
188 MYLOGE("Failed to copy file: %s\n", strerror(errno));
189 }
190 return false;
191 }
192
UnlinkAndLogOnError(const std::string & file)193 static bool UnlinkAndLogOnError(const std::string& file) {
194 if (unlink(file.c_str())) {
195 MYLOGE("Failed to unlink file (%s): %s\n", file.c_str(), strerror(errno));
196 return false;
197 }
198 return true;
199 }
200
IsFileEmpty(const std::string & file_path)201 static bool IsFileEmpty(const std::string& file_path) {
202 std::ifstream file(file_path, std::ios::binary | std::ios::ate);
203 if(file.bad()) {
204 MYLOGE("Cannot open file: %s\n", file_path.c_str());
205 return true;
206 }
207 return file.tellg() <= 0;
208 }
209
GetModuleMetadataVersion()210 int64_t GetModuleMetadataVersion() {
211 auto binder = defaultServiceManager()->getService(android::String16("package_native"));
212 if (binder == nullptr) {
213 MYLOGE("Failed to retrieve package_native service");
214 return 0L;
215 }
216 auto package_service = android::interface_cast<content::pm::IPackageManagerNative>(binder);
217 std::string package_name;
218 auto status = package_service->getModuleMetadataPackageName(&package_name);
219 if (!status.isOk()) {
220 MYLOGE("Failed to retrieve module metadata package name: %s", status.toString8().c_str());
221 return 0L;
222 }
223 MYLOGD("Module metadata package name: %s", package_name.c_str());
224 int64_t version_code;
225 status = package_service->getVersionCodeForPackage(android::String16(package_name.c_str()),
226 &version_code);
227 if (!status.isOk()) {
228 MYLOGE("Failed to retrieve module metadata version: %s", status.toString8().c_str());
229 return 0L;
230 }
231 return version_code;
232 }
233
234 } // namespace
235 } // namespace os
236 } // namespace android
237
RunCommand(const std::string & title,const std::vector<std::string> & fullCommand,const CommandOptions & options=CommandOptions::DEFAULT)238 static int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand,
239 const CommandOptions& options = CommandOptions::DEFAULT) {
240 return ds.RunCommand(title, fullCommand, options);
241 }
RunDumpsys(const std::string & title,const std::vector<std::string> & dumpsysArgs,const CommandOptions & options=Dumpstate::DEFAULT_DUMPSYS,long dumpsysTimeoutMs=0)242 static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
243 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
244 long dumpsysTimeoutMs = 0) {
245 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs);
246 }
DumpFile(const std::string & title,const std::string & path)247 static int DumpFile(const std::string& title, const std::string& path) {
248 return ds.DumpFile(title, path);
249 }
250
251 // Relative directory (inside the zip) for all files copied as-is into the bugreport.
252 static const std::string ZIP_ROOT_DIR = "FS";
253
254 static const std::string kProtoPath = "proto/";
255 static const std::string kProtoExt = ".proto";
256 static const std::string kDumpstateBoardFiles[] = {
257 "dumpstate_board.txt",
258 "dumpstate_board.bin"
259 };
260 static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
261
262 static constexpr char PROPERTY_EXTRA_OPTIONS[] = "dumpstate.options";
263 static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
264 static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
265 static constexpr char PROPERTY_EXTRA_TITLE[] = "dumpstate.options.title";
266 static constexpr char PROPERTY_EXTRA_DESCRIPTION[] = "dumpstate.options.description";
267
268 static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
269
270 /*
271 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
272 * The returned vector is sorted by the mtimes of the dumps. If |limit_by_mtime|
273 * is set, the vector only contains files that were written in the last 30 minutes.
274 * If |limit_by_count| is set, the vector only contains the ten latest files.
275 */
GetDumpFds(const std::string & dir_path,const std::string & file_prefix,bool limit_by_mtime,bool limit_by_count=true)276 static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
277 const std::string& file_prefix,
278 bool limit_by_mtime,
279 bool limit_by_count = true) {
280 const time_t thirty_minutes_ago = ds.now_ - 60 * 30;
281
282 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
283
284 if (dump_dir == nullptr) {
285 MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno));
286 return std::vector<DumpData>();
287 }
288
289 std::vector<DumpData> dump_data;
290 struct dirent* entry = nullptr;
291 while ((entry = readdir(dump_dir.get()))) {
292 if (entry->d_type != DT_REG) {
293 continue;
294 }
295
296 const std::string base_name(entry->d_name);
297 if (base_name.find(file_prefix) != 0) {
298 continue;
299 }
300
301 const std::string abs_path = dir_path + base_name;
302 android::base::unique_fd fd(
303 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
304 if (fd == -1) {
305 MYLOGW("Unable to open dump file %s: %s\n", abs_path.c_str(), strerror(errno));
306 break;
307 }
308
309 struct stat st = {};
310 if (fstat(fd, &st) == -1) {
311 MYLOGW("Unable to stat dump file %s: %s\n", abs_path.c_str(), strerror(errno));
312 continue;
313 }
314
315 if (limit_by_mtime && st.st_mtime < thirty_minutes_ago) {
316 MYLOGI("Excluding stale dump file: %s\n", abs_path.c_str());
317 continue;
318 }
319
320 dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
321 }
322
323 // Sort in descending modification time so that we only keep the newest
324 // reports if |limit_by_count| is true.
325 std::sort(dump_data.begin(), dump_data.end(),
326 [](const DumpData& d1, const DumpData& d2) { return d1.mtime > d2.mtime; });
327
328 if (limit_by_count && dump_data.size() > 10) {
329 dump_data.erase(dump_data.begin() + 10, dump_data.end());
330 }
331
332 return dump_data;
333 }
334
AddDumps(const std::vector<DumpData>::const_iterator start,const std::vector<DumpData>::const_iterator end,const char * type_name,const bool add_to_zip)335 static bool AddDumps(const std::vector<DumpData>::const_iterator start,
336 const std::vector<DumpData>::const_iterator end,
337 const char* type_name, const bool add_to_zip) {
338 bool dumped = false;
339 for (auto it = start; it != end; ++it) {
340 const std::string& name = it->name;
341 const int fd = it->fd;
342 dumped = true;
343
344 // Seek to the beginning of the file before dumping any data. A given
345 // DumpData entry might be dumped multiple times in the report.
346 //
347 // For example, the most recent ANR entry is dumped to the body of the
348 // main entry and it also shows up as a separate entry in the bugreport
349 // ZIP file.
350 if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) {
351 MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(),
352 strerror(errno));
353 }
354
355 if (ds.IsZipping() && add_to_zip) {
356 if (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd, /* timeout = */ 0ms) != OK) {
357 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
358 }
359 } else {
360 dump_file_from_fd(type_name, name.c_str(), fd);
361 }
362 }
363
364 return dumped;
365 }
366
367 // for_each_pid() callback to get mount info about a process.
do_mountinfo(int pid,const char * name)368 void do_mountinfo(int pid, const char* name __attribute__((unused))) {
369 char path[PATH_MAX];
370
371 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
372 // are added.
373 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
374 char linkname[PATH_MAX];
375 ssize_t r = readlink(path, linkname, PATH_MAX);
376 if (r == -1) {
377 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
378 return;
379 }
380 linkname[r] = '\0';
381
382 if (mount_points.find(linkname) == mount_points.end()) {
383 // First time this mount point was found: add it
384 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
385 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
386 mount_points.insert(linkname);
387 } else {
388 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
389 }
390 }
391 }
392
add_mountinfo()393 void add_mountinfo() {
394 if (!ds.IsZipping()) return;
395 std::string title = "MOUNT INFO";
396 mount_points.clear();
397 DurationReporter duration_reporter(title, true);
398 for_each_pid(do_mountinfo, nullptr);
399 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
400 }
401
dump_dev_files(const char * title,const char * driverpath,const char * filename)402 static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
403 {
404 DIR *d;
405 struct dirent *de;
406 char path[PATH_MAX];
407
408 d = opendir(driverpath);
409 if (d == nullptr) {
410 return;
411 }
412
413 while ((de = readdir(d))) {
414 if (de->d_type != DT_LNK) {
415 continue;
416 }
417 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
418 DumpFile(title, path);
419 }
420
421 closedir(d);
422 }
423
424
425
426 // dump anrd's trace and add to the zip file.
427 // 1. check if anrd is running on this device.
428 // 2. send a SIGUSR1 to its pid which will dump anrd's trace.
429 // 3. wait until the trace generation completes and add to the zip file.
dump_anrd_trace()430 static bool dump_anrd_trace() {
431 unsigned int pid;
432 char buf[50], path[PATH_MAX];
433 struct dirent *trace;
434 struct stat st;
435 DIR *trace_dir;
436 int retry = 5;
437 long max_ctime = 0, old_mtime;
438 long long cur_size = 0;
439 const char *trace_path = "/data/misc/anrd/";
440
441 if (!ds.IsZipping()) {
442 MYLOGE("Not dumping anrd trace because it's not a zipped bugreport\n");
443 return false;
444 }
445
446 // find anrd's pid if it is running.
447 pid = GetPidByName("/system/bin/anrd");
448
449 if (pid > 0) {
450 if (stat(trace_path, &st) == 0) {
451 old_mtime = st.st_mtime;
452 } else {
453 MYLOGE("Failed to find: %s\n", trace_path);
454 return false;
455 }
456
457 // send SIGUSR1 to the anrd to generate a trace.
458 sprintf(buf, "%u", pid);
459 if (RunCommand("ANRD_DUMP", {"kill", "-SIGUSR1", buf},
460 CommandOptions::WithTimeout(1).Build())) {
461 MYLOGE("anrd signal timed out. Please manually collect trace\n");
462 return false;
463 }
464
465 while (retry-- > 0 && old_mtime == st.st_mtime) {
466 sleep(1);
467 stat(trace_path, &st);
468 }
469
470 if (retry < 0 && old_mtime == st.st_mtime) {
471 MYLOGE("Failed to stat %s or trace creation timeout\n", trace_path);
472 return false;
473 }
474
475 // identify the trace file by its creation time.
476 if (!(trace_dir = opendir(trace_path))) {
477 MYLOGE("Can't open trace file under %s\n", trace_path);
478 }
479 while ((trace = readdir(trace_dir))) {
480 if (strcmp(trace->d_name, ".") == 0
481 || strcmp(trace->d_name, "..") == 0) {
482 continue;
483 }
484 sprintf(path, "%s%s", trace_path, trace->d_name);
485 if (stat(path, &st) == 0) {
486 if (st.st_ctime > max_ctime) {
487 max_ctime = st.st_ctime;
488 sprintf(buf, "%s", trace->d_name);
489 }
490 }
491 }
492 closedir(trace_dir);
493
494 // Wait until the dump completes by checking the size of the trace.
495 if (max_ctime > 0) {
496 sprintf(path, "%s%s", trace_path, buf);
497 while(true) {
498 sleep(1);
499 if (stat(path, &st) == 0) {
500 if (st.st_size == cur_size) {
501 break;
502 } else if (st.st_size > cur_size) {
503 cur_size = st.st_size;
504 } else {
505 return false;
506 }
507 } else {
508 MYLOGE("Cant stat() %s anymore\n", path);
509 return false;
510 }
511 }
512 // Add to the zip file.
513 if (!ds.AddZipEntry("anrd_trace.txt", path)) {
514 MYLOGE("Unable to add anrd_trace file %s to zip file\n", path);
515 } else {
516 android::os::UnlinkAndLogOnError(path);
517 return true;
518 }
519 } else {
520 MYLOGE("Can't stats any trace file under %s\n", trace_path);
521 }
522 }
523 return false;
524 }
525
skip_not_stat(const char * path)526 static bool skip_not_stat(const char *path) {
527 static const char stat[] = "/stat";
528 size_t len = strlen(path);
529 if (path[len - 1] == '/') { /* Directory? */
530 return false;
531 }
532 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
533 }
534
skip_none(const char * path)535 static bool skip_none(const char* path __attribute__((unused))) {
536 return false;
537 }
538
539 unsigned long worst_write_perf = 20000; /* in KB/s */
540
541 //
542 // stat offsets
543 // Name units description
544 // ---- ----- -----------
545 // read I/Os requests number of read I/Os processed
546 #define __STAT_READ_IOS 0
547 // read merges requests number of read I/Os merged with in-queue I/O
548 #define __STAT_READ_MERGES 1
549 // read sectors sectors number of sectors read
550 #define __STAT_READ_SECTORS 2
551 // read ticks milliseconds total wait time for read requests
552 #define __STAT_READ_TICKS 3
553 // write I/Os requests number of write I/Os processed
554 #define __STAT_WRITE_IOS 4
555 // write merges requests number of write I/Os merged with in-queue I/O
556 #define __STAT_WRITE_MERGES 5
557 // write sectors sectors number of sectors written
558 #define __STAT_WRITE_SECTORS 6
559 // write ticks milliseconds total wait time for write requests
560 #define __STAT_WRITE_TICKS 7
561 // in_flight requests number of I/Os currently in flight
562 #define __STAT_IN_FLIGHT 8
563 // io_ticks milliseconds total time this block device has been active
564 #define __STAT_IO_TICKS 9
565 // time_in_queue milliseconds total wait time for all requests
566 #define __STAT_IN_QUEUE 10
567 #define __STAT_NUMBER_FIELD 11
568 //
569 // read I/Os, write I/Os
570 // =====================
571 //
572 // These values increment when an I/O request completes.
573 //
574 // read merges, write merges
575 // =========================
576 //
577 // These values increment when an I/O request is merged with an
578 // already-queued I/O request.
579 //
580 // read sectors, write sectors
581 // ===========================
582 //
583 // These values count the number of sectors read from or written to this
584 // block device. The "sectors" in question are the standard UNIX 512-byte
585 // sectors, not any device- or filesystem-specific block size. The
586 // counters are incremented when the I/O completes.
587 #define SECTOR_SIZE 512
588 //
589 // read ticks, write ticks
590 // =======================
591 //
592 // These values count the number of milliseconds that I/O requests have
593 // waited on this block device. If there are multiple I/O requests waiting,
594 // these values will increase at a rate greater than 1000/second; for
595 // example, if 60 read requests wait for an average of 30 ms, the read_ticks
596 // field will increase by 60*30 = 1800.
597 //
598 // in_flight
599 // =========
600 //
601 // This value counts the number of I/O requests that have been issued to
602 // the device driver but have not yet completed. It does not include I/O
603 // requests that are in the queue but not yet issued to the device driver.
604 //
605 // io_ticks
606 // ========
607 //
608 // This value counts the number of milliseconds during which the device has
609 // had I/O requests queued.
610 //
611 // time_in_queue
612 // =============
613 //
614 // This value counts the number of milliseconds that I/O requests have waited
615 // on this block device. If there are multiple I/O requests waiting, this
616 // value will increase as the product of the number of milliseconds times the
617 // number of requests waiting (see "read ticks" above for an example).
618 #define S_TO_MS 1000
619 //
620
dump_stat_from_fd(const char * title __unused,const char * path,int fd)621 static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
622 unsigned long long fields[__STAT_NUMBER_FIELD];
623 bool z;
624 char *cp, *buffer = nullptr;
625 size_t i = 0;
626 FILE *fp = fdopen(dup(fd), "rb");
627 getline(&buffer, &i, fp);
628 fclose(fp);
629 if (!buffer) {
630 return -errno;
631 }
632 i = strlen(buffer);
633 while ((i > 0) && (buffer[i - 1] == '\n')) {
634 buffer[--i] = '\0';
635 }
636 if (!*buffer) {
637 free(buffer);
638 return 0;
639 }
640 z = true;
641 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
642 fields[i] = strtoull(cp, &cp, 10);
643 if (fields[i] != 0) {
644 z = false;
645 }
646 }
647 if (z) { /* never accessed */
648 free(buffer);
649 return 0;
650 }
651
652 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
653 path += sizeof(BLK_DEV_SYS_DIR) - 1;
654 }
655
656 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
657 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
658 "W-wait", "in-fli", "activ", "T-wait", path, buffer);
659 free(buffer);
660
661 if (fields[__STAT_IO_TICKS]) {
662 unsigned long read_perf = 0;
663 unsigned long read_ios = 0;
664 if (fields[__STAT_READ_TICKS]) {
665 unsigned long long divisor = fields[__STAT_READ_TICKS]
666 * fields[__STAT_IO_TICKS];
667 read_perf = ((unsigned long long)SECTOR_SIZE
668 * fields[__STAT_READ_SECTORS]
669 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
670 / divisor;
671 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
672 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
673 / divisor;
674 }
675
676 unsigned long write_perf = 0;
677 unsigned long write_ios = 0;
678 if (fields[__STAT_WRITE_TICKS]) {
679 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
680 * fields[__STAT_IO_TICKS];
681 write_perf = ((unsigned long long)SECTOR_SIZE
682 * fields[__STAT_WRITE_SECTORS]
683 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
684 / divisor;
685 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
686 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
687 / divisor;
688 }
689
690 unsigned queue = (fields[__STAT_IN_QUEUE]
691 + (fields[__STAT_IO_TICKS] >> 1))
692 / fields[__STAT_IO_TICKS];
693
694 if (!write_perf && !write_ios) {
695 printf("%-30s: perf(ios) rd: %luKB/s(%lu/s) q: %u\n", path, read_perf, read_ios, queue);
696 } else {
697 printf("%-30s: perf(ios) rd: %luKB/s(%lu/s) wr: %luKB/s(%lu/s) q: %u\n", path, read_perf,
698 read_ios, write_perf, write_ios, queue);
699 }
700
701 /* bugreport timeout factor adjustment */
702 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
703 worst_write_perf = write_perf;
704 }
705 }
706 return 0;
707 }
708
709 static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
710
711 /* timeout in ms to read a list of buffers */
logcat_timeout(const std::vector<std::string> & buffers)712 static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
713 unsigned long timeout_ms = 0;
714 for (const auto& buffer : buffers) {
715 log_id_t id = android_name_to_log_id(buffer.c_str());
716 unsigned long property_size = __android_logger_get_buffer_size(id);
717 /* Engineering margin is ten-fold our guess */
718 timeout_ms += 10 * (property_size + worst_write_perf) / worst_write_perf;
719 }
720 return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
721 }
722
ConsentCallback()723 Dumpstate::ConsentCallback::ConsentCallback() : result_(UNAVAILABLE), start_time_(Nanotime()) {
724 }
725
onReportApproved()726 android::binder::Status Dumpstate::ConsentCallback::onReportApproved() {
727 std::lock_guard<std::mutex> lock(lock_);
728 result_ = APPROVED;
729 MYLOGD("User approved consent to share bugreport\n");
730 return android::binder::Status::ok();
731 }
732
onReportDenied()733 android::binder::Status Dumpstate::ConsentCallback::onReportDenied() {
734 std::lock_guard<std::mutex> lock(lock_);
735 result_ = DENIED;
736 MYLOGW("User denied consent to share bugreport\n");
737 return android::binder::Status::ok();
738 }
739
getResult()740 UserConsentResult Dumpstate::ConsentCallback::getResult() {
741 std::lock_guard<std::mutex> lock(lock_);
742 return result_;
743 }
744
getElapsedTimeMs() const745 uint64_t Dumpstate::ConsentCallback::getElapsedTimeMs() const {
746 return Nanotime() - start_time_;
747 }
748
PrintHeader() const749 void Dumpstate::PrintHeader() const {
750 std::string build, fingerprint, radio, bootloader, network;
751 char date[80];
752
753 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
754 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
755 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
756 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
757 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
758 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
759
760 printf("========================================================\n");
761 printf("== dumpstate: %s\n", date);
762 printf("========================================================\n");
763
764 printf("\n");
765 printf("Build: %s\n", build.c_str());
766 // NOTE: fingerprint entry format is important for other tools.
767 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
768 printf("Bootloader: %s\n", bootloader.c_str());
769 printf("Radio: %s\n", radio.c_str());
770 printf("Network: %s\n", network.c_str());
771 int64_t module_metadata_version = android::os::GetModuleMetadataVersion();
772 if (module_metadata_version != 0) {
773 printf("Module Metadata version: %" PRId64 "\n", module_metadata_version);
774 }
775
776 printf("Kernel: ");
777 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
778 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
779 printf("Uptime: ");
780 RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"},
781 CommandOptions::WithTimeout(1).Always().Build());
782 printf("Bugreport format version: %s\n", version_.c_str());
783 printf("Dumpstate info: id=%d pid=%d dry_run=%d args=%s extra_options=%s\n", id_, pid_,
784 PropertiesHelper::IsDryRun(), options_->args.c_str(), options_->extra_options.c_str());
785 printf("\n");
786 }
787
788 // List of file extensions that can cause a zip file attachment to be rejected by some email
789 // service providers.
790 static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
791 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
792 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
793 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
794 };
795
AddZipEntryFromFd(const std::string & entry_name,int fd,std::chrono::milliseconds timeout=0ms)796 status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd,
797 std::chrono::milliseconds timeout = 0ms) {
798 if (!IsZipping()) {
799 MYLOGD("Not adding zip entry %s from fd because it's not a zipped bugreport\n",
800 entry_name.c_str());
801 return INVALID_OPERATION;
802 }
803 std::string valid_name = entry_name;
804
805 // Rename extension if necessary.
806 size_t idx = entry_name.rfind('.');
807 if (idx != std::string::npos) {
808 std::string extension = entry_name.substr(idx);
809 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
810 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
811 valid_name = entry_name + ".renamed";
812 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
813 }
814 }
815
816 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
817 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
818 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), ZipWriter::kCompress,
819 get_mtime(fd, ds.now_));
820 if (err != 0) {
821 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
822 ZipWriter::ErrorCodeString(err));
823 return UNKNOWN_ERROR;
824 }
825 bool finished_entry = false;
826 auto finish_entry = [this, &finished_entry] {
827 if (!finished_entry) {
828 // This should only be called when we're going to return an earlier error,
829 // which would've been logged. This may imply the file is already corrupt
830 // and any further logging from FinishEntry is more likely to mislead than
831 // not.
832 this->zip_writer_->FinishEntry();
833 }
834 };
835 auto scope_guard = android::base::make_scope_guard(finish_entry);
836 auto start = std::chrono::steady_clock::now();
837 auto end = start + timeout;
838 struct pollfd pfd = {fd, POLLIN};
839
840 std::vector<uint8_t> buffer(65536);
841 while (1) {
842 if (timeout.count() > 0) {
843 // lambda to recalculate the timeout.
844 auto time_left_ms = [end]() {
845 auto now = std::chrono::steady_clock::now();
846 auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
847 return std::max(diff.count(), 0LL);
848 };
849
850 int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
851 if (rc < 0) {
852 MYLOGE("Error in poll while adding from fd to zip entry %s:%s\n",
853 entry_name.c_str(), strerror(errno));
854 return -errno;
855 } else if (rc == 0) {
856 MYLOGE("Timed out adding from fd to zip entry %s:%s Timeout:%lldms\n",
857 entry_name.c_str(), strerror(errno), timeout.count());
858 return TIMED_OUT;
859 }
860 }
861
862 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
863 if (bytes_read == 0) {
864 break;
865 } else if (bytes_read == -1) {
866 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
867 return -errno;
868 }
869 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
870 if (err) {
871 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
872 return UNKNOWN_ERROR;
873 }
874 }
875
876 err = zip_writer_->FinishEntry();
877 finished_entry = true;
878 if (err != 0) {
879 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
880 return UNKNOWN_ERROR;
881 }
882
883 return OK;
884 }
885
AddZipEntry(const std::string & entry_name,const std::string & entry_path)886 bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
887 android::base::unique_fd fd(
888 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
889 if (fd == -1) {
890 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
891 return false;
892 }
893
894 return (AddZipEntryFromFd(entry_name, fd.get()) == OK);
895 }
896
897 /* adds a file to the existing zipped bugreport */
_add_file_from_fd(const char * title,const char * path,int fd)898 static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
899 return (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) == OK) ? 0 : 1;
900 }
901
AddDir(const std::string & dir,bool recursive)902 void Dumpstate::AddDir(const std::string& dir, bool recursive) {
903 if (!IsZipping()) {
904 MYLOGD("Not adding dir %s because it's not a zipped bugreport\n", dir.c_str());
905 return;
906 }
907 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
908 DurationReporter duration_reporter(dir, true);
909 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
910 }
911
AddTextZipEntry(const std::string & entry_name,const std::string & content)912 bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
913 if (!IsZipping()) {
914 MYLOGD("Not adding text zip entry %s because it's not a zipped bugreport\n",
915 entry_name.c_str());
916 return false;
917 }
918 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
919 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, ds.now_);
920 if (err != 0) {
921 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
922 ZipWriter::ErrorCodeString(err));
923 return false;
924 }
925
926 err = zip_writer_->WriteBytes(content.c_str(), content.length());
927 if (err != 0) {
928 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
929 ZipWriter::ErrorCodeString(err));
930 return false;
931 }
932
933 err = zip_writer_->FinishEntry();
934 if (err != 0) {
935 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
936 return false;
937 }
938
939 return true;
940 }
941
DoKmsg()942 static void DoKmsg() {
943 struct stat st;
944 if (!stat(PSTORE_LAST_KMSG, &st)) {
945 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
946 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
947 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
948 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
949 } else {
950 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
951 DumpFile("LAST KMSG", "/proc/last_kmsg");
952 }
953 }
954
DoKernelLogcat()955 static void DoKernelLogcat() {
956 unsigned long timeout_ms = logcat_timeout({"kernel"});
957 RunCommand(
958 "KERNEL LOG",
959 {"logcat", "-b", "kernel", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
960 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
961 }
962
DoLogcat()963 static void DoLogcat() {
964 unsigned long timeout_ms;
965 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
966 // calculate timeout
967 timeout_ms = logcat_timeout({"main", "system", "crash"});
968 RunCommand("SYSTEM LOG",
969 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
970 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
971 timeout_ms = logcat_timeout({"events"});
972 RunCommand(
973 "EVENT LOG",
974 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
975 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
976 timeout_ms = logcat_timeout({"stats"});
977 RunCommand(
978 "STATS LOG",
979 {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
980 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
981 timeout_ms = logcat_timeout({"radio"});
982 RunCommand(
983 "RADIO LOG",
984 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
985 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
986
987 RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
988
989 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
990 RunCommand("LAST LOGCAT", {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable",
991 "-v", "uid", "-d", "*:v"});
992 }
993
DumpIpTablesAsRoot()994 static void DumpIpTablesAsRoot() {
995 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
996 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
997 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
998 /* no ip6 nat */
999 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
1000 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
1001 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
1002 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
1003 }
1004
AddAnrTraceDir(const bool add_to_zip,const std::string & anr_traces_dir)1005 static void AddAnrTraceDir(const bool add_to_zip, const std::string& anr_traces_dir) {
1006 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
1007 anr_traces_dir.c_str());
1008
1009 // If we're here, dump_traces_path will always be a temporary file
1010 // (created with mkostemp or similar) that contains dumps taken earlier
1011 // on in the process.
1012 if (dump_traces_path != nullptr) {
1013 if (add_to_zip) {
1014 ds.AddZipEntry(ZIP_ROOT_DIR + anr_traces_dir + "/traces-just-now.txt", dump_traces_path);
1015 } else {
1016 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
1017 dump_traces_path);
1018 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
1019 }
1020
1021 const int ret = unlink(dump_traces_path);
1022 if (ret == -1) {
1023 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
1024 strerror(errno));
1025 }
1026 }
1027
1028 // Add a specific message for the first ANR Dump.
1029 if (ds.anr_data_.size() > 0) {
1030 AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1,
1031 "VM TRACES AT LAST ANR", add_to_zip);
1032
1033 // The "last" ANR will always be included as separate entry in the zip file. In addition,
1034 // it will be present in the body of the main entry if |add_to_zip| == false.
1035 //
1036 // Historical ANRs are always included as separate entries in the bugreport zip file.
1037 AddDumps(ds.anr_data_.begin() + ((add_to_zip) ? 1 : 0), ds.anr_data_.end(),
1038 "HISTORICAL ANR", true /* add_to_zip */);
1039 } else {
1040 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
1041 }
1042 }
1043
AddAnrTraceFiles()1044 static void AddAnrTraceFiles() {
1045 const bool add_to_zip = ds.IsZipping() && ds.version_ == VERSION_SPLIT_ANR;
1046
1047 std::string anr_traces_dir = "/data/anr";
1048
1049 AddAnrTraceDir(add_to_zip, anr_traces_dir);
1050
1051 RunCommand("ANR FILES", {"ls", "-lt", ANR_DIR});
1052
1053 // Slow traces for slow operations.
1054 struct stat st;
1055 int i = 0;
1056 while (true) {
1057 const std::string slow_trace_path =
1058 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
1059 if (stat(slow_trace_path.c_str(), &st)) {
1060 // No traces file at this index, done with the files.
1061 break;
1062 }
1063 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
1064 i++;
1065 }
1066 }
1067
DumpBlockStatFiles()1068 static void DumpBlockStatFiles() {
1069 DurationReporter duration_reporter("DUMP BLOCK STAT");
1070
1071 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
1072
1073 if (dirptr == nullptr) {
1074 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1075 return;
1076 }
1077
1078 printf("------ DUMP BLOCK STAT ------\n\n");
1079 while (struct dirent *d = readdir(dirptr.get())) {
1080 if ((d->d_name[0] == '.')
1081 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1082 || (d->d_name[1] == '\0'))) {
1083 continue;
1084 }
1085 const std::string new_path =
1086 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1087 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1088 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1089 printf("\n");
1090 }
1091 return;
1092 }
1093
DumpPacketStats()1094 static void DumpPacketStats() {
1095 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
1096 DumpFile("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
1097 DumpFile("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
1098 DumpFile("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
1099 DumpFile("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
1100 }
1101
DumpIpAddrAndRules()1102 static void DumpIpAddrAndRules() {
1103 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
1104 RunCommand("NETWORK INTERFACES", {"ip", "link"});
1105 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1106 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1107 RunCommand("IP RULES", {"ip", "rule", "show"});
1108 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1109 }
1110
RunDumpsysTextByPriority(const std::string & title,int priority,std::chrono::milliseconds timeout,std::chrono::milliseconds service_timeout)1111 static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, int priority,
1112 std::chrono::milliseconds timeout,
1113 std::chrono::milliseconds service_timeout) {
1114 auto start = std::chrono::steady_clock::now();
1115 sp<android::IServiceManager> sm = defaultServiceManager();
1116 Dumpsys dumpsys(sm.get());
1117 Vector<String16> args;
1118 Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
1119 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1120 for (const String16& service : services) {
1121 RETURN_IF_USER_DENIED_CONSENT();
1122 std::string path(title);
1123 path.append(" - ").append(String8(service).c_str());
1124 DumpstateSectionReporter section_reporter(path, ds.listener_, ds.report_section_);
1125 size_t bytes_written = 0;
1126 status_t status = dumpsys.startDumpThread(service, args);
1127 if (status == OK) {
1128 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1129 std::chrono::duration<double> elapsed_seconds;
1130 status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
1131 /* as_proto = */ false, elapsed_seconds, bytes_written);
1132 section_reporter.setSize(bytes_written);
1133 dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
1134 bool dump_complete = (status == OK);
1135 dumpsys.stopDumpThread(dump_complete);
1136 }
1137 section_reporter.setStatus(status);
1138
1139 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1140 std::chrono::steady_clock::now() - start);
1141 if (elapsed_duration > timeout) {
1142 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1143 elapsed_duration.count());
1144 break;
1145 }
1146 }
1147 return Dumpstate::RunStatus::OK;
1148 }
1149
RunDumpsysText(const std::string & title,int priority,std::chrono::milliseconds timeout,std::chrono::milliseconds service_timeout)1150 static void RunDumpsysText(const std::string& title, int priority,
1151 std::chrono::milliseconds timeout,
1152 std::chrono::milliseconds service_timeout) {
1153 DurationReporter duration_reporter(title);
1154 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1155 fsync(STDOUT_FILENO);
1156 RunDumpsysTextByPriority(title, priority, timeout, service_timeout);
1157 }
1158
1159 /* Dump all services registered with Normal or Default priority. */
RunDumpsysTextNormalPriority(const std::string & title,std::chrono::milliseconds timeout,std::chrono::milliseconds service_timeout)1160 static Dumpstate::RunStatus RunDumpsysTextNormalPriority(const std::string& title,
1161 std::chrono::milliseconds timeout,
1162 std::chrono::milliseconds service_timeout) {
1163 DurationReporter duration_reporter(title);
1164 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1165 fsync(STDOUT_FILENO);
1166 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout,
1167 service_timeout);
1168
1169 RETURN_IF_USER_DENIED_CONSENT();
1170
1171 return RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1172 service_timeout);
1173 }
1174
RunDumpsysProto(const std::string & title,int priority,std::chrono::milliseconds timeout,std::chrono::milliseconds service_timeout)1175 static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priority,
1176 std::chrono::milliseconds timeout,
1177 std::chrono::milliseconds service_timeout) {
1178 if (!ds.IsZipping()) {
1179 MYLOGD("Not dumping %s because it's not a zipped bugreport\n", title.c_str());
1180 return Dumpstate::RunStatus::OK;
1181 }
1182 sp<android::IServiceManager> sm = defaultServiceManager();
1183 Dumpsys dumpsys(sm.get());
1184 Vector<String16> args;
1185 Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
1186 DurationReporter duration_reporter(title);
1187
1188 auto start = std::chrono::steady_clock::now();
1189 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
1190 for (const String16& service : services) {
1191 RETURN_IF_USER_DENIED_CONSENT();
1192 std::string path(kProtoPath);
1193 path.append(String8(service).c_str());
1194 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
1195 path.append("_CRITICAL");
1196 } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
1197 path.append("_HIGH");
1198 }
1199 path.append(kProtoExt);
1200 DumpstateSectionReporter section_reporter(path, ds.listener_, ds.report_section_);
1201 status_t status = dumpsys.startDumpThread(service, args);
1202 if (status == OK) {
1203 status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
1204 bool dumpTerminated = (status == OK);
1205 dumpsys.stopDumpThread(dumpTerminated);
1206 }
1207 ZipWriter::FileEntry file_entry;
1208 ds.zip_writer_->GetLastEntry(&file_entry);
1209 section_reporter.setSize(file_entry.compressed_size);
1210 section_reporter.setStatus(status);
1211
1212 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1213 std::chrono::steady_clock::now() - start);
1214 if (elapsed_duration > timeout) {
1215 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1216 elapsed_duration.count());
1217 break;
1218 }
1219 }
1220 return Dumpstate::RunStatus::OK;
1221 }
1222
1223 // Runs dumpsys on services that must dump first and will take less than 100ms to dump.
RunDumpsysCritical()1224 static Dumpstate::RunStatus RunDumpsysCritical() {
1225 RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1226 /* timeout= */ 5s, /* service_timeout= */ 500ms);
1227
1228 RETURN_IF_USER_DENIED_CONSENT();
1229
1230 return RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1231 /* timeout= */ 5s, /* service_timeout= */ 500ms);
1232 }
1233
1234 // Runs dumpsys on services that must dump first but can take up to 250ms to dump.
RunDumpsysHigh()1235 static Dumpstate::RunStatus RunDumpsysHigh() {
1236 // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
1237 // high priority. Reduce timeout once they are able to dump in a shorter time or
1238 // moved to a parallel task.
1239 RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1240 /* timeout= */ 90s, /* service_timeout= */ 30s);
1241
1242 RETURN_IF_USER_DENIED_CONSENT();
1243
1244 return RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1245 /* timeout= */ 5s, /* service_timeout= */ 1s);
1246 }
1247
1248 // Runs dumpsys on services that must dump but can take up to 10s to dump.
RunDumpsysNormal()1249 static Dumpstate::RunStatus RunDumpsysNormal() {
1250 RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
1251
1252 RETURN_IF_USER_DENIED_CONSENT();
1253
1254 return RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1255 /* timeout= */ 90s, /* service_timeout= */ 10s);
1256 }
1257
DumpHals()1258 static void DumpHals() {
1259 if (!ds.IsZipping()) {
1260 RunCommand("HARDWARE HALS", {"lshal", "-lVSietrpc", "--types=b,c,l,z", "--debug"},
1261 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
1262 return;
1263 }
1264 DurationReporter duration_reporter("DUMP HALS");
1265 RunCommand("HARDWARE HALS", {"lshal", "-lVSietrpc", "--types=b,c,l,z"},
1266 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
1267
1268 using android::hidl::manager::V1_0::IServiceManager;
1269 using android::hardware::defaultServiceManager;
1270
1271 sp<IServiceManager> sm = defaultServiceManager();
1272 if (sm == nullptr) {
1273 MYLOGE("Could not retrieve hwservicemanager to dump hals.\n");
1274 return;
1275 }
1276
1277 auto ret = sm->list([&](const auto& interfaces) {
1278 for (const std::string& interface : interfaces) {
1279 std::string cleanName = interface;
1280 std::replace_if(cleanName.begin(),
1281 cleanName.end(),
1282 [](char c) {
1283 return !isalnum(c) &&
1284 std::string("@-_:.").find(c) == std::string::npos;
1285 }, '_');
1286 const std::string path = ds.bugreport_internal_dir_ + "/lshal_debug_" + cleanName;
1287
1288 {
1289 auto fd = android::base::unique_fd(
1290 TEMP_FAILURE_RETRY(open(path.c_str(),
1291 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1292 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1293 if (fd < 0) {
1294 MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str());
1295 continue;
1296 }
1297 RunCommandToFd(fd,
1298 "",
1299 {"lshal", "debug", "-E", interface},
1300 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1301
1302 bool empty = 0 == lseek(fd, 0, SEEK_END);
1303 if (!empty) {
1304 ds.AddZipEntry("lshal-debug/" + cleanName + ".txt", path);
1305 }
1306 }
1307
1308 unlink(path.c_str());
1309 }
1310 });
1311
1312 if (!ret.isOk()) {
1313 MYLOGE("Could not list hals from hwservicemanager.\n");
1314 }
1315 }
1316
1317 // Dumps various things. Returns early with status USER_CONSENT_DENIED if user denies consent
1318 // via the consent they are shown. Ignores other errors that occur while running various
1319 // commands. The consent checking is currently done around long running tasks, which happen to
1320 // be distributed fairly evenly throughout the function.
dumpstate()1321 static Dumpstate::RunStatus dumpstate() {
1322 DurationReporter duration_reporter("DUMPSTATE");
1323
1324 // Dump various things. Note that anything that takes "long" (i.e. several seconds) should
1325 // check intermittently (if it's intrerruptable like a foreach on pids) and/or should be wrapped
1326 // in a consent check (via RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK).
1327 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
1328 RunCommand("UPTIME", {"uptime"});
1329 DumpBlockStatFiles();
1330 dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
1331 DumpFile("MEMORY INFO", "/proc/meminfo");
1332 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
1333 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
1334
1335 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "PROCRANK", {"procrank"}, AS_ROOT_20);
1336
1337 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1338 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1339 DumpFile("SLAB INFO", "/proc/slabinfo");
1340 DumpFile("ZONEINFO", "/proc/zoneinfo");
1341 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1342 DumpFile("BUDDYINFO", "/proc/buddyinfo");
1343 DumpFile("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
1344
1345 DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources");
1346 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
1347 DumpFile("KERNEL SYNC", "/d/sync");
1348
1349 RunCommand("PROCESSES AND THREADS",
1350 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
1351
1352 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "LIBRANK", {"librank"},
1353 CommandOptions::AS_ROOT);
1354
1355 DumpHals();
1356
1357 RunCommand("PRINTENV", {"printenv"});
1358 RunCommand("NETSTAT", {"netstat", "-nW"});
1359 struct stat s;
1360 if (stat("/proc/modules", &s) != 0) {
1361 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1362 } else {
1363 RunCommand("LSMOD", {"lsmod"});
1364 }
1365
1366 if (__android_logger_property_get_bool(
1367 "ro.logd.kernel", BOOL_DEFAULT_TRUE | BOOL_DEFAULT_FLAG_ENG | BOOL_DEFAULT_FLAG_SVELTE)) {
1368 DoKernelLogcat();
1369 } else {
1370 do_dmesg();
1371 }
1372
1373 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
1374
1375 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(for_each_pid, do_showmap, "SMAPS OF ALL PROCESSES");
1376
1377 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
1378 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
1379
1380 /* Dump Bluetooth HCI logs */
1381 ds.AddDir("/data/misc/bluetooth/logs", true);
1382
1383 if (!ds.do_early_screenshot_) {
1384 MYLOGI("taking late screenshot\n");
1385 ds.TakeScreenshot();
1386 }
1387
1388 DoLogcat();
1389
1390 AddAnrTraceFiles();
1391
1392 // NOTE: tombstones are always added as separate entries in the zip archive
1393 // and are not interspersed with the main report.
1394 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
1395 "TOMBSTONE", true /* add_to_zip */);
1396 if (!tombstones_dumped) {
1397 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
1398 }
1399
1400 DumpPacketStats();
1401
1402 RunDumpsys("EBPF MAP STATS", {"netd", "trafficcontroller"});
1403
1404 DoKmsg();
1405
1406 DumpIpAddrAndRules();
1407
1408 dump_route_tables();
1409
1410 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1411 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1412 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
1413
1414 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysHigh);
1415
1416 RunCommand("SYSTEM PROPERTIES", {"getprop"});
1417
1418 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
1419
1420 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
1421
1422 RunCommand("LAST RADIO LOG", {"parse_radio_log", "/proc/last_radio_log"});
1423
1424 /* Binder state is expensive to look at as it uses a lot of memory. */
1425 DumpFile("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
1426 DumpFile("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
1427 DumpFile("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
1428 DumpFile("BINDER STATS", "/sys/kernel/debug/binder/stats");
1429 DumpFile("BINDER STATE", "/sys/kernel/debug/binder/state");
1430
1431 RunDumpsys("WINSCOPE TRACE", {"window", "trace"});
1432 /* Add window and surface trace files. */
1433 if (!PropertiesHelper::IsUserBuild()) {
1434 ds.AddDir(WMTRACE_DATA_DIR, false);
1435 }
1436
1437 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(ds.DumpstateBoard);
1438
1439 /* Migrate the ril_dumpstate to a device specific dumpstate? */
1440 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1441 if (rilDumpstateTimeout > 0) {
1442 // su does not exist on user builds, so try running without it.
1443 // This way any implementations of vril-dump that do not require
1444 // root can run on user builds.
1445 CommandOptions::CommandOptionsBuilder options =
1446 CommandOptions::WithTimeout(rilDumpstateTimeout);
1447 if (!PropertiesHelper::IsUserBuild()) {
1448 options.AsRoot();
1449 }
1450 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
1451 }
1452
1453 printf("========================================================\n");
1454 printf("== Android Framework Services\n");
1455 printf("========================================================\n");
1456
1457 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal);
1458
1459 printf("========================================================\n");
1460 printf("== Checkins\n");
1461 printf("========================================================\n");
1462
1463 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1464
1465 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsys, "CHECKIN MEMINFO", {"meminfo", "--checkin"});
1466
1467 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"});
1468 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"});
1469 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"});
1470 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"});
1471
1472 printf("========================================================\n");
1473 printf("== Running Application Activities\n");
1474 printf("========================================================\n");
1475
1476 // The following dumpsys internally collects output from running apps, so it can take a long
1477 // time. So let's extend the timeout.
1478
1479 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1480
1481 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS);
1482
1483 printf("========================================================\n");
1484 printf("== Running Application Services (platform)\n");
1485 printf("========================================================\n");
1486
1487 RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
1488 DUMPSYS_COMPONENTS_OPTIONS);
1489
1490 printf("========================================================\n");
1491 printf("== Running Application Services (non-platform)\n");
1492 printf("========================================================\n");
1493
1494 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1495 DUMPSYS_COMPONENTS_OPTIONS);
1496
1497 printf("========================================================\n");
1498 printf("== Running Application Providers (platform)\n");
1499 printf("========================================================\n");
1500
1501 RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
1502 DUMPSYS_COMPONENTS_OPTIONS);
1503
1504 printf("========================================================\n");
1505 printf("== Running Application Providers (non-platform)\n");
1506 printf("========================================================\n");
1507
1508 RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1509 DUMPSYS_COMPONENTS_OPTIONS);
1510
1511 printf("========================================================\n");
1512 printf("== Dropbox crashes\n");
1513 printf("========================================================\n");
1514
1515 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1516 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1517
1518 printf("========================================================\n");
1519 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1520 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1521 printf("========================================================\n");
1522 printf("== dumpstate: done (id %d)\n", ds.id_);
1523 printf("========================================================\n");
1524
1525 printf("========================================================\n");
1526 printf("== Obtaining statsd metadata\n");
1527 printf("========================================================\n");
1528 // This differs from the usual dumpsys stats, which is the stats report data.
1529 RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
1530 return Dumpstate::RunStatus::OK;
1531 }
1532
1533 /*
1534 * Dumps state for the default case; drops root after it's no longer necessary.
1535 *
1536 * Returns RunStatus::OK if everything went fine.
1537 * Returns RunStatus::ERROR if there was an error.
1538 * Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport
1539 * with the caller.
1540 */
DumpstateDefault()1541 static Dumpstate::RunStatus DumpstateDefault() {
1542 // Try to dump anrd trace if the daemon is running.
1543 dump_anrd_trace();
1544
1545 // Invoking the following dumpsys calls before DumpTraces() to try and
1546 // keep the system stats as close to its initial state as possible.
1547 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysCritical);
1548
1549 /* collect stack traces from Dalvik and native processes (needs root) */
1550 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(ds.DumpTraces, &dump_traces_path);
1551
1552 /* Run some operations that require root. */
1553 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping());
1554 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping());
1555
1556 ds.AddDir(RECOVERY_DIR, true);
1557 ds.AddDir(RECOVERY_DATA_DIR, true);
1558 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
1559 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1560 if (!PropertiesHelper::IsUserBuild()) {
1561 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1562 ds.AddDir(PROFILE_DATA_DIR_REF, true);
1563 }
1564 add_mountinfo();
1565 DumpIpTablesAsRoot();
1566
1567 // Capture any IPSec policies in play. No keys are exposed here.
1568 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1569
1570 // Dump IPsec stats. No keys are exposed here.
1571 DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
1572
1573 // Run ss as root so we can see socket marks.
1574 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1575
1576 // Run iotop as root to show top 100 IO threads
1577 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1578
1579 // Gather shared memory buffer info if the product implements it
1580 struct stat st;
1581 if (!stat("/product/bin/dmabuf_dump", &st)) {
1582 RunCommand("Dmabuf dump", {"/product/bin/dmabuf_dump"});
1583 }
1584
1585 if (!DropRootUser()) {
1586 return Dumpstate::RunStatus::ERROR;
1587 }
1588
1589 RETURN_IF_USER_DENIED_CONSENT();
1590 return dumpstate();
1591 }
1592
1593 // This method collects common dumpsys for telephony and wifi
DumpstateRadioCommon()1594 static void DumpstateRadioCommon() {
1595 DumpIpTablesAsRoot();
1596
1597 if (!DropRootUser()) {
1598 return;
1599 }
1600
1601 do_dmesg();
1602 DoLogcat();
1603 DumpPacketStats();
1604 DoKmsg();
1605 DumpIpAddrAndRules();
1606 dump_route_tables();
1607
1608 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
1609 CommandOptions::WithTimeout(10).Build());
1610 }
1611
1612 // This method collects dumpsys for telephony debugging only
DumpstateTelephonyOnly()1613 static void DumpstateTelephonyOnly() {
1614 DurationReporter duration_reporter("DUMPSTATE");
1615 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1616
1617 DumpstateRadioCommon();
1618
1619 RunCommand("SYSTEM PROPERTIES", {"getprop"});
1620
1621 printf("========================================================\n");
1622 printf("== Android Framework Services\n");
1623 printf("========================================================\n");
1624
1625 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1626 SEC_TO_MSEC(10));
1627 RunDumpsys("DUMPSYS", {"connmetrics"}, CommandOptions::WithTimeout(90).Build(),
1628 SEC_TO_MSEC(10));
1629 RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
1630 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
1631 SEC_TO_MSEC(10));
1632 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
1633 SEC_TO_MSEC(10));
1634 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
1635 SEC_TO_MSEC(10));
1636
1637 printf("========================================================\n");
1638 printf("== Running Application Services\n");
1639 printf("========================================================\n");
1640
1641 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
1642
1643 printf("========================================================\n");
1644 printf("== Running Application Services (non-platform)\n");
1645 printf("========================================================\n");
1646
1647 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1648 DUMPSYS_COMPONENTS_OPTIONS);
1649
1650 printf("========================================================\n");
1651 printf("== Checkins\n");
1652 printf("========================================================\n");
1653
1654 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1655
1656 printf("========================================================\n");
1657 printf("== dumpstate: done (id %d)\n", ds.id_);
1658 printf("========================================================\n");
1659 }
1660
1661 // This method collects dumpsys for wifi debugging only
DumpstateWifiOnly()1662 static void DumpstateWifiOnly() {
1663 DurationReporter duration_reporter("DUMPSTATE");
1664
1665 DumpstateRadioCommon();
1666
1667 printf("========================================================\n");
1668 printf("== Android Framework Services\n");
1669 printf("========================================================\n");
1670
1671 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1672 SEC_TO_MSEC(10));
1673 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
1674 SEC_TO_MSEC(10));
1675
1676 DumpHals();
1677
1678 printf("========================================================\n");
1679 printf("== dumpstate: done (id %d)\n", ds.id_);
1680 printf("========================================================\n");
1681 }
1682
DumpTraces(const char ** path)1683 Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
1684 DurationReporter duration_reporter("DUMP TRACES");
1685
1686 const std::string temp_file_pattern = "/data/anr/dumptrace_XXXXXX";
1687 const size_t buf_size = temp_file_pattern.length() + 1;
1688 std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
1689 memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
1690
1691 // Create a new, empty file to receive all trace dumps.
1692 //
1693 // TODO: This can be simplified once we remove support for the old style
1694 // dumps. We can have a file descriptor passed in to dump_traces instead
1695 // of creating a file, closing it and then reopening it again.
1696 android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
1697 if (fd < 0) {
1698 MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
1699 return RunStatus::OK;
1700 }
1701
1702 // Nobody should have access to this temporary file except dumpstate, but we
1703 // temporarily grant 'read' to 'others' here because this file is created
1704 // when tombstoned is still running as root, but dumped after dropping. This
1705 // can go away once support for old style dumping has.
1706 const int chmod_ret = fchmod(fd, 0666);
1707 if (chmod_ret < 0) {
1708 MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
1709 return RunStatus::OK;
1710 }
1711
1712 std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
1713 if (proc.get() == nullptr) {
1714 MYLOGE("opendir /proc failed: %s\n", strerror(errno));
1715 return RunStatus::OK;
1716 }
1717
1718 // Number of times process dumping has timed out. If we encounter too many
1719 // failures, we'll give up.
1720 int timeout_failures = 0;
1721 bool dalvik_found = false;
1722
1723 const std::set<int> hal_pids = get_interesting_hal_pids();
1724
1725 struct dirent* d;
1726 while ((d = readdir(proc.get()))) {
1727 RETURN_IF_USER_DENIED_CONSENT();
1728 int pid = atoi(d->d_name);
1729 if (pid <= 0) {
1730 continue;
1731 }
1732
1733 const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
1734 std::string exe;
1735 if (!android::base::Readlink(link_name, &exe)) {
1736 continue;
1737 }
1738
1739 bool is_java_process;
1740 if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
1741 // Don't bother dumping backtraces for the zygote.
1742 if (IsZygote(pid)) {
1743 continue;
1744 }
1745
1746 dalvik_found = true;
1747 is_java_process = true;
1748 } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
1749 is_java_process = false;
1750 } else {
1751 // Probably a native process we don't care about, continue.
1752 continue;
1753 }
1754
1755 // If 3 backtrace dumps fail in a row, consider debuggerd dead.
1756 if (timeout_failures == 3) {
1757 dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
1758 break;
1759 }
1760
1761 const uint64_t start = Nanotime();
1762 const int ret = dump_backtrace_to_file_timeout(
1763 pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace,
1764 is_java_process ? 5 : 20, fd);
1765
1766 if (ret == -1) {
1767 // For consistency, the header and footer to this message match those
1768 // dumped by debuggerd in the success case.
1769 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
1770 dprintf(fd, "Dump failed, likely due to a timeout.\n");
1771 dprintf(fd, "---- end %d ----", pid);
1772 timeout_failures++;
1773 continue;
1774 }
1775
1776 // We've successfully dumped stack traces, reset the failure count
1777 // and write a summary of the elapsed time to the file and continue with the
1778 // next process.
1779 timeout_failures = 0;
1780
1781 dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
1782 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
1783 }
1784
1785 if (!dalvik_found) {
1786 MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
1787 }
1788
1789 *path = file_name_buf.release();
1790 return RunStatus::OK;
1791 }
1792
DumpstateBoard()1793 void Dumpstate::DumpstateBoard() {
1794 DurationReporter duration_reporter("dumpstate_board()");
1795 printf("========================================================\n");
1796 printf("== Board\n");
1797 printf("========================================================\n");
1798
1799 if (!IsZipping()) {
1800 MYLOGD("Not dumping board info because it's not a zipped bugreport\n");
1801 return;
1802 }
1803
1804 std::vector<std::string> paths;
1805 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
1806 for (int i = 0; i < NUM_OF_DUMPS; i++) {
1807 paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
1808 kDumpstateBoardFiles[i].c_str()));
1809 remover.emplace_back(android::base::make_scope_guard(
1810 std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
1811 }
1812
1813 sp<IDumpstateDevice> dumpstate_device(IDumpstateDevice::getService());
1814 if (dumpstate_device == nullptr) {
1815 MYLOGE("No IDumpstateDevice implementation\n");
1816 return;
1817 }
1818
1819 using ScopedNativeHandle =
1820 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
1821 ScopedNativeHandle handle(native_handle_create(static_cast<int>(paths.size()), 0),
1822 [](native_handle_t* handle) {
1823 native_handle_close(handle);
1824 native_handle_delete(handle);
1825 });
1826 if (handle == nullptr) {
1827 MYLOGE("Could not create native_handle\n");
1828 return;
1829 }
1830
1831 // TODO(128270426): Check for consent in between?
1832 for (size_t i = 0; i < paths.size(); i++) {
1833 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
1834
1835 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
1836 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1837 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1838 if (fd < 0) {
1839 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
1840 return;
1841 }
1842 handle.get()->data[i] = fd.release();
1843 }
1844
1845 // Given that bugreport is required to diagnose failures, it's better to
1846 // set an arbitrary amount of timeout for IDumpstateDevice than to block the
1847 // rest of bugreport. In the timeout case, we will kill dumpstate board HAL
1848 // and grab whatever dumped
1849 std::packaged_task<bool()>
1850 dumpstate_task([paths, dumpstate_device, &handle]() -> bool {
1851 android::hardware::Return<void> status = dumpstate_device->dumpstateBoard(handle.get());
1852 if (!status.isOk()) {
1853 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
1854 return false;
1855 }
1856 return true;
1857 });
1858
1859 auto result = dumpstate_task.get_future();
1860 std::thread(std::move(dumpstate_task)).detach();
1861
1862 constexpr size_t timeout_sec = 30;
1863 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
1864 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate vendor HAL\n", timeout_sec);
1865 if (!android::base::SetProperty("ctl.interface_restart",
1866 android::base::StringPrintf("%s/default",
1867 IDumpstateDevice::descriptor))) {
1868 MYLOGE("Couldn't restart dumpstate HAL\n");
1869 }
1870 }
1871 // Wait some time for init to kill dumpstate vendor HAL
1872 constexpr size_t killing_timeout_sec = 10;
1873 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
1874 MYLOGE("killing dumpstateBoard timed out after %zus, continue and "
1875 "there might be racing in content\n", killing_timeout_sec);
1876 }
1877
1878 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
1879 for (size_t i = 0; i < paths.size(); i++) {
1880 struct stat s;
1881 if (fstat(handle.get()->data[i], &s) == -1) {
1882 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(),
1883 strerror(errno));
1884 file_sizes[i] = -1;
1885 continue;
1886 }
1887 file_sizes[i] = s.st_size;
1888 }
1889
1890 for (size_t i = 0; i < paths.size(); i++) {
1891 if (file_sizes[i] == -1) {
1892 continue;
1893 }
1894 if (file_sizes[i] == 0) {
1895 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
1896 continue;
1897 }
1898 AddZipEntry(kDumpstateBoardFiles[i], paths[i]);
1899 }
1900
1901 printf("*** See dumpstate-board.txt entry ***\n");
1902 }
1903
ShowUsage()1904 static void ShowUsage() {
1905 fprintf(stderr,
1906 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file] [-d] [-p] "
1907 "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
1908 " -h: display this help message\n"
1909 " -b: play sound file instead of vibrate, at beginning of job\n"
1910 " -e: play sound file instead of vibrate, at end of job\n"
1911 " -o: write to file (instead of stdout)\n"
1912 " -d: append date to filename (requires -o)\n"
1913 " -p: capture screenshot to filename.png (requires -o)\n"
1914 " -z: generate zipped file (requires -o)\n"
1915 " -s: write output to control socket (for init)\n"
1916 " -S: write file location to control socket (for init; requires -o and -z)\n"
1917 " -q: disable vibrate\n"
1918 " -B: send broadcast when finished (requires -o)\n"
1919 " -P: send broadcast when started and update system properties on "
1920 "progress (requires -o and -B)\n"
1921 " -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
1922 "shouldn't be used with -P)\n"
1923 " -w: start binder service and make it wait for a call to startBugreport\n"
1924 " -v: prints the dumpstate header and exit\n");
1925 }
1926
register_sig_handler()1927 static void register_sig_handler() {
1928 signal(SIGPIPE, SIG_IGN);
1929 }
1930
FinishZipFile()1931 bool Dumpstate::FinishZipFile() {
1932 std::string entry_name = base_name_ + "-" + name_ + ".txt";
1933 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
1934 tmp_path_.c_str());
1935 // Final timestamp
1936 char date[80];
1937 time_t the_real_now_please_stand_up = time(nullptr);
1938 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
1939 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
1940 the_real_now_please_stand_up - ds.now_);
1941
1942 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
1943 MYLOGE("Failed to add text entry to .zip file\n");
1944 return false;
1945 }
1946 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
1947 MYLOGE("Failed to add main_entry.txt to .zip file\n");
1948 return false;
1949 }
1950
1951 // Add log file (which contains stderr output) to zip...
1952 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
1953 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
1954 MYLOGE("Failed to add dumpstate log to .zip file\n");
1955 return false;
1956 }
1957 // TODO: Should truncate the existing file.
1958 // ... and re-open it for further logging.
1959 if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
1960 return false;
1961 }
1962 fprintf(stderr, "\n");
1963
1964 int32_t err = zip_writer_->Finish();
1965 if (err != 0) {
1966 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
1967 return false;
1968 }
1969
1970 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
1971 ds.zip_file.reset(nullptr);
1972
1973 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
1974 android::os::UnlinkAndLogOnError(tmp_path_);
1975
1976 return true;
1977 }
1978
SHA256_file_hash(const std::string & filepath)1979 static std::string SHA256_file_hash(const std::string& filepath) {
1980 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK
1981 | O_CLOEXEC | O_NOFOLLOW)));
1982 if (fd == -1) {
1983 MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
1984 return nullptr;
1985 }
1986
1987 SHA256_CTX ctx;
1988 SHA256_Init(&ctx);
1989
1990 std::vector<uint8_t> buffer(65536);
1991 while (1) {
1992 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
1993 if (bytes_read == 0) {
1994 break;
1995 } else if (bytes_read == -1) {
1996 MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
1997 return nullptr;
1998 }
1999
2000 SHA256_Update(&ctx, buffer.data(), bytes_read);
2001 }
2002
2003 uint8_t hash[SHA256_DIGEST_LENGTH];
2004 SHA256_Final(hash, &ctx);
2005
2006 char hash_buffer[SHA256_DIGEST_LENGTH * 2 + 1];
2007 for(size_t i = 0; i < SHA256_DIGEST_LENGTH; i++) {
2008 sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
2009 }
2010 hash_buffer[sizeof(hash_buffer) - 1] = 0;
2011 return std::string(hash_buffer);
2012 }
2013
SendBroadcast(const std::string & action,const std::vector<std::string> & args)2014 static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) {
2015 // clang-format off
2016 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0",
2017 "--receiver-foreground", "--receiver-include-background", "-a", action};
2018 // clang-format on
2019
2020 am.insert(am.end(), args.begin(), args.end());
2021
2022 RunCommand("", am,
2023 CommandOptions::WithTimeout(20)
2024 .Log("Sending broadcast: '%s'\n")
2025 .Always()
2026 .DropRoot()
2027 .RedirectStderr()
2028 .Build());
2029 }
2030
Vibrate(int duration_ms)2031 static void Vibrate(int duration_ms) {
2032 // clang-format off
2033 RunCommand("", {"cmd", "vibrator", "vibrate", std::to_string(duration_ms), "dumpstate"},
2034 CommandOptions::WithTimeout(10)
2035 .Log("Vibrate: '%s'\n")
2036 .Always()
2037 .Build());
2038 // clang-format on
2039 }
2040
MaybeResolveSymlink(std::string * path)2041 static void MaybeResolveSymlink(std::string* path) {
2042 std::string resolved_path;
2043 if (android::base::Readlink(*path, &resolved_path)) {
2044 *path = resolved_path;
2045 }
2046 }
2047
2048 /*
2049 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
2050 * if we are writing zip files and adds the version file.
2051 */
PrepareToWriteToFile()2052 static void PrepareToWriteToFile() {
2053 MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2054
2055 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2056 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
2057 ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
2058 if (ds.options_->do_add_date) {
2059 char date[80];
2060 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2061 ds.name_ = date;
2062 } else {
2063 ds.name_ = "undated";
2064 }
2065
2066 if (ds.options_->telephony_only) {
2067 ds.base_name_ += "-telephony";
2068 } else if (ds.options_->wifi_only) {
2069 ds.base_name_ += "-wifi";
2070 }
2071
2072 if (ds.options_->do_fb) {
2073 ds.screenshot_path_ = ds.GetPath(".png");
2074 }
2075 ds.tmp_path_ = ds.GetPath(".tmp");
2076 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2077
2078 std::string destination = ds.options_->bugreport_fd.get() != -1
2079 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
2080 : ds.bugreport_internal_dir_.c_str();
2081 MYLOGD(
2082 "Bugreport dir: %s\n"
2083 "Base name: %s\n"
2084 "Suffix: %s\n"
2085 "Log path: %s\n"
2086 "Temporary path: %s\n"
2087 "Screenshot path: %s\n",
2088 destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2089 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
2090
2091 if (ds.options_->do_zip_file) {
2092 ds.path_ = ds.GetPath(".zip");
2093 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2094 create_parent_dirs(ds.path_.c_str());
2095 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2096 if (ds.zip_file == nullptr) {
2097 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2098 } else {
2099 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2100 }
2101 ds.AddTextZipEntry("version.txt", ds.version_);
2102 }
2103 }
2104
2105 /*
2106 * Finalizes writing to the file by renaming or zipping the tmp file to the final location,
2107 * printing zipped file status, etc.
2108 */
FinalizeFile()2109 static void FinalizeFile() {
2110 /* check if user changed the suffix using system properties */
2111 std::string name =
2112 android::base::GetProperty(android::base::StringPrintf("dumpstate.%d.name", ds.pid_), "");
2113 bool change_suffix = false;
2114 if (!name.empty()) {
2115 /* must whitelist which characters are allowed, otherwise it could cross directories */
2116 std::regex valid_regex("^[-_a-zA-Z0-9]+$");
2117 if (std::regex_match(name.c_str(), valid_regex)) {
2118 change_suffix = true;
2119 } else {
2120 MYLOGE("invalid suffix provided by user: %s\n", name.c_str());
2121 }
2122 }
2123 if (change_suffix) {
2124 MYLOGI("changing suffix from %s to %s\n", ds.name_.c_str(), name.c_str());
2125 ds.name_ = name;
2126 if (!ds.screenshot_path_.empty()) {
2127 std::string new_screenshot_path = ds.GetPath(".png");
2128 if (rename(ds.screenshot_path_.c_str(), new_screenshot_path.c_str())) {
2129 MYLOGE("rename(%s, %s): %s\n", ds.screenshot_path_.c_str(),
2130 new_screenshot_path.c_str(), strerror(errno));
2131 } else {
2132 ds.screenshot_path_ = new_screenshot_path;
2133 }
2134 }
2135 }
2136
2137 bool do_text_file = true;
2138 if (ds.options_->do_zip_file) {
2139 if (!ds.FinishZipFile()) {
2140 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
2141 do_text_file = true;
2142 } else {
2143 do_text_file = false;
2144 // If the user has changed the suffix, we need to change the zip file name.
2145 std::string new_path = ds.GetPath(".zip");
2146 if (ds.path_ != new_path) {
2147 MYLOGD("Renaming zip file from %s to %s\n", ds.path_.c_str(), new_path.c_str());
2148 if (rename(ds.path_.c_str(), new_path.c_str())) {
2149 MYLOGE("rename(%s, %s): %s\n", ds.path_.c_str(), new_path.c_str(),
2150 strerror(errno));
2151 } else {
2152 ds.path_ = new_path;
2153 }
2154 }
2155 }
2156 }
2157 if (do_text_file) {
2158 ds.path_ = ds.GetPath(".txt");
2159 MYLOGD("Generating .txt bugreport at %s from %s\n", ds.path_.c_str(), ds.tmp_path_.c_str());
2160 if (rename(ds.tmp_path_.c_str(), ds.path_.c_str())) {
2161 MYLOGE("rename(%s, %s): %s\n", ds.tmp_path_.c_str(), ds.path_.c_str(), strerror(errno));
2162 ds.path_.clear();
2163 }
2164 }
2165 if (ds.options_->use_control_socket) {
2166 if (do_text_file) {
2167 dprintf(ds.control_socket_fd_,
2168 "FAIL:could not create zip file, check %s "
2169 "for more details\n",
2170 ds.log_path_.c_str());
2171 } else {
2172 dprintf(ds.control_socket_fd_, "OK:%s\n", ds.path_.c_str());
2173 }
2174 }
2175 }
2176
2177 /* Broadcasts that we are done with the bugreport */
SendBugreportFinishedBroadcast()2178 static void SendBugreportFinishedBroadcast() {
2179 // TODO(b/111441001): use callback instead of broadcast.
2180 if (!ds.path_.empty()) {
2181 MYLOGI("Final bugreport path: %s\n", ds.path_.c_str());
2182 // clang-format off
2183
2184 std::vector<std::string> am_args = {
2185 "--receiver-permission", "android.permission.DUMP",
2186 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
2187 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
2188 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
2189 "--es", "android.intent.extra.BUGREPORT", ds.path_,
2190 "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_
2191 };
2192 // clang-format on
2193 if (ds.options_->do_fb && !android::os::IsFileEmpty(ds.screenshot_path_)) {
2194 am_args.push_back("--es");
2195 am_args.push_back("android.intent.extra.SCREENSHOT");
2196 am_args.push_back(ds.screenshot_path_);
2197 }
2198 if (!ds.options_->notification_title.empty()) {
2199 am_args.push_back("--es");
2200 am_args.push_back("android.intent.extra.TITLE");
2201 am_args.push_back(ds.options_->notification_title);
2202 if (!ds.options_->notification_description.empty()) {
2203 am_args.push_back("--es");
2204 am_args.push_back("android.intent.extra.DESCRIPTION");
2205 am_args.push_back(ds.options_->notification_description);
2206 }
2207 }
2208 if (ds.options_->is_remote_mode) {
2209 am_args.push_back("--es");
2210 am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
2211 am_args.push_back(SHA256_file_hash(ds.path_));
2212 SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED", am_args);
2213 } else {
2214 SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args);
2215 }
2216 } else {
2217 MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
2218 }
2219 }
2220
ModeToString(Dumpstate::BugreportMode mode)2221 static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2222 switch (mode) {
2223 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2224 return "BUGREPORT_FULL";
2225 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2226 return "BUGREPORT_INTERACTIVE";
2227 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2228 return "BUGREPORT_REMOTE";
2229 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2230 return "BUGREPORT_WEAR";
2231 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2232 return "BUGREPORT_TELEPHONY";
2233 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2234 return "BUGREPORT_WIFI";
2235 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2236 return "BUGREPORT_DEFAULT";
2237 }
2238 }
2239
SetOptionsFromMode(Dumpstate::BugreportMode mode,Dumpstate::DumpOptions * options)2240 static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options) {
2241 options->extra_options = ModeToString(mode);
2242 switch (mode) {
2243 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2244 options->do_broadcast = true;
2245 options->do_fb = true;
2246 break;
2247 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2248 // Currently, the dumpstate binder is only used by Shell to update progress.
2249 options->do_start_service = true;
2250 options->do_progress_updates = true;
2251 options->do_fb = false;
2252 options->do_broadcast = true;
2253 break;
2254 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2255 options->do_vibrate = false;
2256 options->is_remote_mode = true;
2257 options->do_fb = false;
2258 options->do_broadcast = true;
2259 break;
2260 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2261 options->do_start_service = true;
2262 options->do_progress_updates = true;
2263 options->do_zip_file = true;
2264 options->do_fb = true;
2265 options->do_broadcast = true;
2266 break;
2267 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2268 options->telephony_only = true;
2269 options->do_fb = false;
2270 options->do_broadcast = true;
2271 break;
2272 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2273 options->wifi_only = true;
2274 options->do_zip_file = true;
2275 options->do_fb = false;
2276 options->do_broadcast = true;
2277 break;
2278 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2279 break;
2280 }
2281 }
2282
getBugreportModeFromProperty()2283 static Dumpstate::BugreportMode getBugreportModeFromProperty() {
2284 // If the system property is not set, it's assumed to be a default bugreport.
2285 Dumpstate::BugreportMode mode = Dumpstate::BugreportMode::BUGREPORT_DEFAULT;
2286
2287 std::string extra_options = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
2288 if (!extra_options.empty()) {
2289 // Framework uses a system property to override some command-line args.
2290 // Currently, it contains the type of the requested bugreport.
2291 if (extra_options == "bugreportplus") {
2292 mode = Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE;
2293 } else if (extra_options == "bugreportfull") {
2294 mode = Dumpstate::BugreportMode::BUGREPORT_FULL;
2295 } else if (extra_options == "bugreportremote") {
2296 mode = Dumpstate::BugreportMode::BUGREPORT_REMOTE;
2297 } else if (extra_options == "bugreportwear") {
2298 mode = Dumpstate::BugreportMode::BUGREPORT_WEAR;
2299 } else if (extra_options == "bugreporttelephony") {
2300 mode = Dumpstate::BugreportMode::BUGREPORT_TELEPHONY;
2301 } else if (extra_options == "bugreportwifi") {
2302 mode = Dumpstate::BugreportMode::BUGREPORT_WIFI;
2303 } else {
2304 MYLOGE("Unknown extra option: %s\n", extra_options.c_str());
2305 }
2306 // Reset the property
2307 android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, "");
2308 }
2309 return mode;
2310 }
2311
2312 // TODO: Move away from system properties when we have options passed via binder calls.
2313 /* Sets runtime options from the system properties and then clears those properties. */
SetOptionsFromProperties(Dumpstate::DumpOptions * options)2314 static void SetOptionsFromProperties(Dumpstate::DumpOptions* options) {
2315 Dumpstate::BugreportMode mode = getBugreportModeFromProperty();
2316 SetOptionsFromMode(mode, options);
2317
2318 options->notification_title = android::base::GetProperty(PROPERTY_EXTRA_TITLE, "");
2319 if (!options->notification_title.empty()) {
2320 // Reset the property
2321 android::base::SetProperty(PROPERTY_EXTRA_TITLE, "");
2322
2323 options->notification_description =
2324 android::base::GetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
2325 if (!options->notification_description.empty()) {
2326 // Reset the property
2327 android::base::SetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
2328 }
2329 MYLOGD("notification (title: %s, description: %s)\n", options->notification_title.c_str(),
2330 options->notification_description.c_str());
2331 }
2332 }
2333
LogDumpOptions(const Dumpstate::DumpOptions & options)2334 static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
2335 MYLOGI("do_zip_file: %d\n", options.do_zip_file);
2336 MYLOGI("do_add_date: %d\n", options.do_add_date);
2337 MYLOGI("do_vibrate: %d\n", options.do_vibrate);
2338 MYLOGI("use_socket: %d\n", options.use_socket);
2339 MYLOGI("use_control_socket: %d\n", options.use_control_socket);
2340 MYLOGI("do_fb: %d\n", options.do_fb);
2341 MYLOGI("do_broadcast: %d\n", options.do_broadcast);
2342 MYLOGI("is_remote_mode: %d\n", options.is_remote_mode);
2343 MYLOGI("show_header_only: %d\n", options.show_header_only);
2344 MYLOGI("do_start_service: %d\n", options.do_start_service);
2345 MYLOGI("telephony_only: %d\n", options.telephony_only);
2346 MYLOGI("wifi_only: %d\n", options.wifi_only);
2347 MYLOGI("do_progress_updates: %d\n", options.do_progress_updates);
2348 MYLOGI("fd: %d\n", options.bugreport_fd.get());
2349 MYLOGI("extra_options: %s\n", options.extra_options.c_str());
2350 MYLOGI("args: %s\n", options.args.c_str());
2351 MYLOGI("notification_title: %s\n", options.notification_title.c_str());
2352 MYLOGI("notification_description: %s\n", options.notification_description.c_str());
2353 }
2354
Initialize(BugreportMode bugreport_mode,const android::base::unique_fd & bugreport_fd_in,const android::base::unique_fd & screenshot_fd_in)2355 void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
2356 const android::base::unique_fd& bugreport_fd_in,
2357 const android::base::unique_fd& screenshot_fd_in) {
2358 // In the new API world, date is always added; output is always a zip file.
2359 // TODO(111441001): remove these options once they are obsolete.
2360 do_add_date = true;
2361 do_zip_file = true;
2362
2363 // Duplicate the fds because the passed in fds don't outlive the binder transaction.
2364 bugreport_fd.reset(dup(bugreport_fd_in.get()));
2365 screenshot_fd.reset(dup(screenshot_fd_in.get()));
2366
2367 extra_options = ModeToString(bugreport_mode);
2368 SetOptionsFromMode(bugreport_mode, this);
2369 }
2370
Initialize(int argc,char * argv[])2371 Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
2372 RunStatus status = RunStatus::OK;
2373 int c;
2374 while ((c = getopt(argc, argv, "dho:svqzpPBRSV:w")) != -1) {
2375 switch (c) {
2376 // clang-format off
2377 case 'd': do_add_date = true; break;
2378 case 'z': do_zip_file = true; break;
2379 // o=use_outfile not supported anymore.
2380 // TODO(b/111441001): Remove when all callers have migrated.
2381 case 'o': break;
2382 case 's': use_socket = true; break;
2383 case 'S': use_control_socket = true; break;
2384 case 'v': show_header_only = true; break;
2385 case 'q': do_vibrate = false; break;
2386 case 'p': do_fb = true; break;
2387 case 'P': do_progress_updates = true; break;
2388 case 'R': is_remote_mode = true; break;
2389 case 'B': do_broadcast = true; break;
2390 case 'V': break; // compatibility no-op
2391 case 'w':
2392 // This was already processed
2393 break;
2394 case 'h':
2395 status = RunStatus::HELP;
2396 break;
2397 default:
2398 fprintf(stderr, "Invalid option: %c\n", c);
2399 status = RunStatus::INVALID_INPUT;
2400 break;
2401 // clang-format on
2402 }
2403 }
2404
2405 // TODO: use helper function to convert argv into a string
2406 for (int i = 0; i < argc; i++) {
2407 args += argv[i];
2408 if (i < argc - 1) {
2409 args += " ";
2410 }
2411 }
2412
2413 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
2414 optind = 1;
2415
2416 SetOptionsFromProperties(this);
2417 return status;
2418 }
2419
ValidateOptions() const2420 bool Dumpstate::DumpOptions::ValidateOptions() const {
2421 if (bugreport_fd.get() != -1 && !do_zip_file) {
2422 return false;
2423 }
2424
2425 if ((do_zip_file || do_add_date || do_progress_updates || do_broadcast) && !OutputToFile()) {
2426 return false;
2427 }
2428
2429 if (use_control_socket && !do_zip_file) {
2430 return false;
2431 }
2432
2433 if (do_progress_updates && !do_broadcast) {
2434 return false;
2435 }
2436
2437 if (is_remote_mode && (do_progress_updates || !do_broadcast || !do_zip_file || !do_add_date)) {
2438 return false;
2439 }
2440 return true;
2441 }
2442
SetOptions(std::unique_ptr<DumpOptions> options)2443 void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
2444 options_ = std::move(options);
2445 }
2446
Run(int32_t calling_uid,const std::string & calling_package)2447 Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
2448 Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
2449 if (listener_ != nullptr) {
2450 switch (status) {
2451 case Dumpstate::RunStatus::OK:
2452 listener_->onFinished();
2453 break;
2454 case Dumpstate::RunStatus::HELP:
2455 break;
2456 case Dumpstate::RunStatus::INVALID_INPUT:
2457 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
2458 break;
2459 case Dumpstate::RunStatus::ERROR:
2460 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
2461 break;
2462 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
2463 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
2464 break;
2465 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
2466 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
2467 break;
2468 }
2469 }
2470 return status;
2471 }
2472
2473 /*
2474 * Dumps relevant information to a bugreport based on the given options.
2475 *
2476 * The bugreport can be dumped to a file or streamed to a socket.
2477 *
2478 * How dumping to file works:
2479 * stdout is redirected to a temporary file. This will later become the main bugreport entry.
2480 * stderr is redirected a log file.
2481 *
2482 * The temporary bugreport is then populated via printfs, dumping contents of files and
2483 * output of commands to stdout.
2484 *
2485 * If zipping, the temporary bugreport file is added to the zip archive. Else it's renamed to final
2486 * text file.
2487 *
2488 * If zipping, a bunch of other files and dumps also get added to the zip archive. The log file also
2489 * gets added to the archive.
2490 *
2491 * Bugreports are first generated in a local directory and later copied to the caller's fd if
2492 * supplied.
2493 */
RunInternal(int32_t calling_uid,const std::string & calling_package)2494 Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
2495 const std::string& calling_package) {
2496 LogDumpOptions(*options_);
2497 if (!options_->ValidateOptions()) {
2498 MYLOGE("Invalid options specified\n");
2499 return RunStatus::INVALID_INPUT;
2500 }
2501 /* set as high priority, and protect from OOM killer */
2502 setpriority(PRIO_PROCESS, 0, -20);
2503
2504 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
2505 if (oom_adj) {
2506 fputs("-1000", oom_adj);
2507 fclose(oom_adj);
2508 } else {
2509 /* fallback to kernels <= 2.6.35 */
2510 oom_adj = fopen("/proc/self/oom_adj", "we");
2511 if (oom_adj) {
2512 fputs("-17", oom_adj);
2513 fclose(oom_adj);
2514 }
2515 }
2516
2517 if (version_ == VERSION_DEFAULT) {
2518 version_ = VERSION_CURRENT;
2519 }
2520
2521 if (version_ != VERSION_CURRENT && version_ != VERSION_SPLIT_ANR) {
2522 MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s')\n",
2523 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
2524 VERSION_SPLIT_ANR.c_str());
2525 return RunStatus::INVALID_INPUT;
2526 }
2527
2528 if (options_->show_header_only) {
2529 PrintHeader();
2530 return RunStatus::OK;
2531 }
2532
2533 if (options_->bugreport_fd.get() != -1) {
2534 // If the output needs to be copied over to the caller's fd, get user consent.
2535 android::String16 package(calling_package.c_str());
2536 CheckUserConsent(calling_uid, package);
2537 }
2538
2539 // Redirect output if needed
2540 bool is_redirecting = options_->OutputToFile();
2541
2542 // TODO: temporarily set progress until it's part of the Dumpstate constructor
2543 std::string stats_path =
2544 is_redirecting
2545 ? android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str())
2546 : "";
2547 progress_.reset(new Progress(stats_path));
2548
2549 /* gets the sequential id */
2550 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
2551 id_ = ++last_id;
2552 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
2553
2554 MYLOGI("begin\n");
2555
2556 register_sig_handler();
2557
2558 // TODO(b/111441001): maybe skip if already started?
2559 if (options_->do_start_service) {
2560 MYLOGI("Starting 'dumpstate' service\n");
2561 android::status_t ret;
2562 if ((ret = android::os::DumpstateService::Start()) != android::OK) {
2563 MYLOGE("Unable to start DumpstateService: %d\n", ret);
2564 }
2565 }
2566
2567 if (PropertiesHelper::IsDryRun()) {
2568 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
2569 }
2570
2571 MYLOGI("dumpstate info: id=%d, args='%s', extra_options= %s)\n", id_, options_->args.c_str(),
2572 options_->extra_options.c_str());
2573
2574 MYLOGI("bugreport format version: %s\n", version_.c_str());
2575
2576 do_early_screenshot_ = options_->do_progress_updates;
2577
2578 // If we are going to use a socket, do it as early as possible
2579 // to avoid timeouts from bugreport.
2580 if (options_->use_socket) {
2581 if (!redirect_to_socket(stdout, "dumpstate")) {
2582 return ERROR;
2583 }
2584 }
2585
2586 if (options_->use_control_socket) {
2587 MYLOGD("Opening control socket\n");
2588 control_socket_fd_ = open_socket("dumpstate");
2589 if (control_socket_fd_ == -1) {
2590 return ERROR;
2591 }
2592 options_->do_progress_updates = 1;
2593 }
2594
2595 if (is_redirecting) {
2596 PrepareToWriteToFile();
2597
2598 if (options_->do_progress_updates) {
2599 if (options_->do_broadcast) {
2600 // clang-format off
2601 std::vector<std::string> am_args = {
2602 "--receiver-permission", "android.permission.DUMP",
2603 "--es", "android.intent.extra.NAME", name_,
2604 "--ei", "android.intent.extra.ID", std::to_string(id_),
2605 "--ei", "android.intent.extra.PID", std::to_string(pid_),
2606 "--ei", "android.intent.extra.MAX", std::to_string(progress_->GetMax()),
2607 };
2608 // clang-format on
2609 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
2610 }
2611 if (options_->use_control_socket) {
2612 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
2613 }
2614 }
2615 }
2616
2617 /* read /proc/cmdline before dropping root */
2618 FILE *cmdline = fopen("/proc/cmdline", "re");
2619 if (cmdline) {
2620 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
2621 fclose(cmdline);
2622 }
2623
2624 if (options_->do_vibrate) {
2625 Vibrate(150);
2626 }
2627
2628 if (options_->do_fb && do_early_screenshot_) {
2629 if (screenshot_path_.empty()) {
2630 // should not have happened
2631 MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
2632 } else {
2633 MYLOGI("taking early screenshot\n");
2634 TakeScreenshot();
2635 }
2636 }
2637
2638 if (options_->do_zip_file && zip_file != nullptr) {
2639 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
2640 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
2641 strerror(errno));
2642 }
2643 }
2644
2645 int dup_stdout_fd;
2646 int dup_stderr_fd;
2647 if (is_redirecting) {
2648 // Redirect stderr to log_path_ for debugging.
2649 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
2650 if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
2651 return ERROR;
2652 }
2653 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
2654 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
2655 strerror(errno));
2656 }
2657
2658 // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
2659 // moved into zip file later, if zipping.
2660 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
2661 // TODO: why not write to a file instead of stdout to overcome this problem?
2662 /* TODO: rather than generating a text file now and zipping it later,
2663 it would be more efficient to redirect stdout to the zip entry
2664 directly, but the libziparchive doesn't support that option yet. */
2665 if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
2666 return ERROR;
2667 }
2668 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
2669 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
2670 tmp_path_.c_str(), strerror(errno));
2671 }
2672 }
2673
2674 // Don't buffer stdout
2675 setvbuf(stdout, nullptr, _IONBF, 0);
2676
2677 // NOTE: there should be no stdout output until now, otherwise it would break the header.
2678 // In particular, DurationReport objects should be created passing 'title, NULL', so their
2679 // duration is logged into MYLOG instead.
2680 PrintHeader();
2681
2682 if (options_->telephony_only) {
2683 DumpstateTelephonyOnly();
2684 DumpstateBoard();
2685 } else if (options_->wifi_only) {
2686 DumpstateWifiOnly();
2687 } else {
2688 // Dump state for the default case. This also drops root.
2689 RunStatus s = DumpstateDefault();
2690 if (s != RunStatus::OK) {
2691 if (s == RunStatus::USER_CONSENT_TIMED_OUT) {
2692 HandleUserConsentDenied();
2693 }
2694 return s;
2695 }
2696 }
2697
2698 /* close output if needed */
2699 if (is_redirecting) {
2700 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
2701 }
2702
2703 // Rename, and/or zip the (now complete) .tmp file within the internal directory.
2704 if (options_->OutputToFile()) {
2705 FinalizeFile();
2706 }
2707
2708 // Share the final file with the caller if the user has consented.
2709 Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
2710 if (options_->bugreport_fd.get() != -1) {
2711 status = CopyBugreportIfUserConsented();
2712 if (status != Dumpstate::RunStatus::OK &&
2713 status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
2714 // Do an early return if there were errors. We make an exception for consent
2715 // timing out because it's possible the user got distracted. In this case the
2716 // bugreport is not shared but made available for manual retrieval.
2717 MYLOGI("User denied consent. Returning\n");
2718 return status;
2719 }
2720 if (options_->do_fb && options_->screenshot_fd.get() != -1) {
2721 bool copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
2722 options_->screenshot_fd.get());
2723 if (copy_succeeded) {
2724 android::os::UnlinkAndLogOnError(screenshot_path_);
2725 }
2726 }
2727 if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
2728 MYLOGI(
2729 "Did not receive user consent yet."
2730 " Will not copy the bugreport artifacts to caller.\n");
2731 const String16 incidentcompanion("incidentcompanion");
2732 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
2733 if (ics != nullptr) {
2734 MYLOGD("Canceling user consent request via incidentcompanion service\n");
2735 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
2736 consent_callback_.get());
2737 } else {
2738 MYLOGD("Unable to cancel user consent; incidentcompanion service unavailable\n");
2739 }
2740 }
2741 }
2742
2743 /* vibrate a few but shortly times to let user know it's finished */
2744 if (options_->do_vibrate) {
2745 for (int i = 0; i < 3; i++) {
2746 Vibrate(75);
2747 usleep((75 + 50) * 1000);
2748 }
2749 }
2750
2751 /* tell activity manager we're done */
2752 if (options_->do_broadcast) {
2753 SendBugreportFinishedBroadcast();
2754 // Note that listener_ is notified in Run();
2755 }
2756
2757 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
2758 progress_->GetInitialMax());
2759 progress_->Save();
2760 MYLOGI("done (id %d)\n", id_);
2761
2762 if (is_redirecting) {
2763 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
2764 }
2765
2766 if (options_->use_control_socket && control_socket_fd_ != -1) {
2767 MYLOGD("Closing control socket\n");
2768 close(control_socket_fd_);
2769 }
2770
2771 tombstone_data_.clear();
2772 anr_data_.clear();
2773
2774 return (consent_callback_ != nullptr &&
2775 consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
2776 ? USER_CONSENT_TIMED_OUT
2777 : RunStatus::OK;
2778 }
2779
CheckUserConsent(int32_t calling_uid,const android::String16 & calling_package)2780 void Dumpstate::CheckUserConsent(int32_t calling_uid, const android::String16& calling_package) {
2781 consent_callback_ = new ConsentCallback();
2782 const String16 incidentcompanion("incidentcompanion");
2783 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
2784 if (ics != nullptr) {
2785 MYLOGD("Checking user consent via incidentcompanion service\n");
2786 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
2787 calling_uid, calling_package, String16(), String16(),
2788 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
2789 } else {
2790 MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
2791 }
2792 }
2793
IsUserConsentDenied() const2794 bool Dumpstate::IsUserConsentDenied() const {
2795 return ds.consent_callback_ != nullptr &&
2796 ds.consent_callback_->getResult() == UserConsentResult::DENIED;
2797 }
2798
CleanupFiles()2799 void Dumpstate::CleanupFiles() {
2800 android::os::UnlinkAndLogOnError(tmp_path_);
2801 android::os::UnlinkAndLogOnError(screenshot_path_);
2802 android::os::UnlinkAndLogOnError(path_);
2803 }
2804
HandleUserConsentDenied()2805 Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
2806 MYLOGD("User denied consent; deleting files and returning\n");
2807 CleanupFiles();
2808 return USER_CONSENT_DENIED;
2809 }
2810
CopyBugreportIfUserConsented()2811 Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented() {
2812 // If the caller has asked to copy the bugreport over to their directory, we need explicit
2813 // user consent.
2814 UserConsentResult consent_result = consent_callback_->getResult();
2815 if (consent_result == UserConsentResult::UNAVAILABLE) {
2816 // User has not responded yet.
2817 uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
2818 if (elapsed_ms < USER_CONSENT_TIMEOUT_MS) {
2819 uint delay_seconds = (USER_CONSENT_TIMEOUT_MS - elapsed_ms) / 1000;
2820 MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
2821 sleep(delay_seconds);
2822 }
2823 consent_result = consent_callback_->getResult();
2824 }
2825 if (consent_result == UserConsentResult::DENIED) {
2826 // User has explicitly denied sharing with the app. To be safe delete the
2827 // internal bugreport & tmp files.
2828 return HandleUserConsentDenied();
2829 }
2830 if (consent_result == UserConsentResult::APPROVED) {
2831 bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
2832 if (copy_succeeded) {
2833 android::os::UnlinkAndLogOnError(path_);
2834 }
2835 return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
2836 } else if (consent_result == UserConsentResult::UNAVAILABLE) {
2837 // consent_result is still UNAVAILABLE. The user has likely not responded yet.
2838 // Since we do not have user consent to share the bugreport it does not get
2839 // copied over to the calling app but remains in the internal directory from
2840 // where the user can manually pull it.
2841 return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
2842 }
2843 // Unknown result; must be a programming error.
2844 MYLOGE("Unknown user consent result:%d\n", consent_result);
2845 return Dumpstate::RunStatus::ERROR;
2846 }
2847
ParseCommandlineAndRun(int argc,char * argv[])2848 Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
2849 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
2850 Dumpstate::RunStatus status = options->Initialize(argc, argv);
2851 if (status == Dumpstate::RunStatus::OK) {
2852 SetOptions(std::move(options));
2853 // When directly running dumpstate binary, the output is not expected to be written
2854 // to any external file descriptor.
2855 assert(options_->bugreport_fd.get() == -1);
2856
2857 // calling_uid and calling_package are for user consent to share the bugreport with
2858 // an app; they are irrelvant here because bugreport is only written to a local
2859 // directory, and not shared.
2860 status = Run(-1 /* calling_uid */, "" /* calling_package */);
2861 }
2862 return status;
2863 }
2864
2865 /* Main entry point for dumpstate binary. */
run_main(int argc,char * argv[])2866 int run_main(int argc, char* argv[]) {
2867 Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
2868
2869 switch (status) {
2870 case Dumpstate::RunStatus::OK:
2871 exit(0);
2872 case Dumpstate::RunStatus::HELP:
2873 ShowUsage();
2874 exit(0);
2875 case Dumpstate::RunStatus::INVALID_INPUT:
2876 fprintf(stderr, "Invalid combination of args\n");
2877 ShowUsage();
2878 exit(1);
2879 case Dumpstate::RunStatus::ERROR:
2880 FALLTHROUGH_INTENDED;
2881 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
2882 FALLTHROUGH_INTENDED;
2883 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
2884 exit(2);
2885 }
2886 }
2887