• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <math.h>
26 #include <poll.h>
27 #include <stdbool.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <sys/mount.h>
32 #include <sys/poll.h>
33 #include <sys/prctl.h>
34 #include <sys/resource.h>
35 #include <sys/stat.h>
36 #include <sys/time.h>
37 #include <sys/wait.h>
38 #include <signal.h>
39 #include <stdarg.h>
40 #include <string.h>
41 #include <sys/capability.h>
42 #include <sys/inotify.h>
43 #include <sys/klog.h>
44 #include <time.h>
45 #include <unistd.h>
46 
47 #include <chrono>
48 #include <cmath>
49 #include <fstream>
50 #include <functional>
51 #include <future>
52 #include <memory>
53 #include <numeric>
54 #include <regex>
55 #include <set>
56 #include <string>
57 #include <utility>
58 #include <vector>
59 
60 #include <aidl/android/hardware/dumpstate/IDumpstateDevice.h>
61 #include <android-base/file.h>
62 #include <android-base/properties.h>
63 #include <android-base/scopeguard.h>
64 #include <android-base/stringprintf.h>
65 #include <android-base/strings.h>
66 #include <android-base/unique_fd.h>
67 #include <android/binder_manager.h>
68 #include <android/binder_process.h>
69 #include <android/content/pm/IPackageManagerNative.h>
70 #include <android/hardware/dumpstate/1.0/IDumpstateDevice.h>
71 #include <android/hardware/dumpstate/1.1/IDumpstateDevice.h>
72 #include <android/hardware/dumpstate/1.1/types.h>
73 #include <android/hidl/manager/1.0/IServiceManager.h>
74 #include <android/os/IIncidentCompanion.h>
75 #include <binder/IServiceManager.h>
76 #include <cutils/native_handle.h>
77 #include <cutils/properties.h>
78 #include <cutils/sockets.h>
79 #include <debuggerd/client.h>
80 #include <dumpsys.h>
81 #include <dumputils/dump_utils.h>
82 #include <hardware_legacy/power.h>
83 #include <hidl/ServiceManagement.h>
84 #include <log/log.h>
85 #include <log/log_read.h>
86 #include <openssl/sha.h>
87 #include <private/android_filesystem_config.h>
88 #include <private/android_logger.h>
89 #include <serviceutils/PriorityDumper.h>
90 #include <utils/StrongPointer.h>
91 #include "DumpstateInternal.h"
92 #include "DumpstateService.h"
93 #include "dumpstate.h"
94 
95 namespace dumpstate_hal_hidl_1_0 = android::hardware::dumpstate::V1_0;
96 namespace dumpstate_hal_hidl = android::hardware::dumpstate::V1_1;
97 namespace dumpstate_hal_aidl = aidl::android::hardware::dumpstate;
98 
99 using ::std::literals::chrono_literals::operator""ms;
100 using ::std::literals::chrono_literals::operator""s;
101 using ::std::placeholders::_1;
102 
103 // TODO: remove once moved to namespace
104 using android::defaultServiceManager;
105 using android::Dumpsys;
106 using android::INVALID_OPERATION;
107 using android::IServiceManager;
108 using android::OK;
109 using android::sp;
110 using android::status_t;
111 using android::String16;
112 using android::String8;
113 using android::TIMED_OUT;
114 using android::UNKNOWN_ERROR;
115 using android::Vector;
116 using android::base::StringPrintf;
117 using android::os::IDumpstateListener;
118 using android::os::dumpstate::CommandOptions;
119 using android::os::dumpstate::DumpFileToFd;
120 using android::os::dumpstate::DumpPool;
121 using android::os::dumpstate::PropertiesHelper;
122 using android::os::dumpstate::TaskQueue;
123 using android::os::dumpstate::WaitForTask;
124 
125 // Keep in sync with
126 // frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
127 static const int TRACE_DUMP_TIMEOUT_MS = 10000; // 10 seconds
128 
129 /* Most simple commands have 10 as timeout, so 5 is a good estimate */
130 static const int32_t WEIGHT_FILE = 5;
131 
132 // TODO: temporary variables and functions used during C++ refactoring
133 static Dumpstate& ds = Dumpstate::GetInstance();
RunCommand(const std::string & title,const std::vector<std::string> & full_command,const CommandOptions & options=CommandOptions::DEFAULT,bool verbose_duration=false,int out_fd=STDOUT_FILENO)134 static int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
135                       const CommandOptions& options = CommandOptions::DEFAULT,
136                       bool verbose_duration = false, int out_fd = STDOUT_FILENO) {
137     return ds.RunCommand(title, full_command, options, verbose_duration, out_fd);
138 }
139 
140 // Reasonable value for max stats.
141 static const int STATS_MAX_N_RUNS = 1000;
142 static const long STATS_MAX_AVERAGE = 100000;
143 
144 CommandOptions Dumpstate::DEFAULT_DUMPSYS = CommandOptions::WithTimeout(30).Build();
145 
146 typedef Dumpstate::ConsentCallback::ConsentResult UserConsentResult;
147 
148 /* read before root is shed */
149 static char cmdline_buf[16384] = "(unknown)";
150 static const char *dump_traces_path = nullptr;
151 static const uint64_t USER_CONSENT_TIMEOUT_MS = 30 * 1000;
152 // Because telephony reports are significantly faster to collect (< 10 seconds vs. > 2 minutes),
153 // it's often the case that they time out far too quickly for consent with such a hefty dialog for
154 // the user to read. For telephony reports only, we increase the default timeout to 2 minutes to
155 // roughly match full reports' durations.
156 static const uint64_t TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS = 2 * 60 * 1000;
157 
158 // TODO: variables and functions below should be part of dumpstate object
159 
160 static std::set<std::string> mount_points;
161 void add_mountinfo();
162 
163 #define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
164 #define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
165 #define BLK_DEV_SYS_DIR "/sys/block"
166 
167 #define RECOVERY_DIR "/cache/recovery"
168 #define RECOVERY_DATA_DIR "/data/misc/recovery"
169 #define UPDATE_ENGINE_LOG_DIR "/data/misc/update_engine_log"
170 #define LOGPERSIST_DATA_DIR "/data/misc/logd"
171 #define PREREBOOT_DATA_DIR "/data/misc/prereboot"
172 #define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
173 #define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
174 #define XFRM_STAT_PROC_FILE "/proc/net/xfrm_stat"
175 #define WLUTIL "/vendor/xbin/wlutil"
176 #define WMTRACE_DATA_DIR "/data/misc/wmtrace"
177 #define OTA_METADATA_DIR "/metadata/ota"
178 #define SNAPSHOTCTL_LOG_DIR "/data/misc/snapshotctl_log"
179 #define LINKERCONFIG_DIR "/linkerconfig"
180 #define PACKAGE_DEX_USE_LIST "/data/system/package-dex-usage.list"
181 #define SYSTEM_TRACE_SNAPSHOT "/data/misc/perfetto-traces/bugreport/systrace.pftrace"
182 #define CGROUPFS_DIR "/sys/fs/cgroup"
183 
184 // TODO(narayan): Since this information has to be kept in sync
185 // with tombstoned, we should just put it in a common header.
186 //
187 // File: system/core/debuggerd/tombstoned/tombstoned.cpp
188 static const std::string TOMBSTONE_DIR = "/data/tombstones/";
189 static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
190 static const std::string ANR_DIR = "/data/anr/";
191 static const std::string ANR_FILE_PREFIX = "anr_";
192 
193 // TODO: temporary variables and functions used during C++ refactoring
194 
195 #define RETURN_IF_USER_DENIED_CONSENT()                                                        \
196     if (ds.IsUserConsentDenied()) {                                                            \
197         MYLOGE("Returning early as user denied consent to share bugreport with calling app."); \
198         return Dumpstate::RunStatus::USER_CONSENT_DENIED;                                      \
199     }
200 
201 // Runs func_ptr, but checks user consent before and after running it. Returns USER_CONSENT_DENIED
202 // if consent is found to be denied.
203 #define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(func_ptr, ...) \
204     RETURN_IF_USER_DENIED_CONSENT();                        \
205     func_ptr(__VA_ARGS__);                                  \
206     RETURN_IF_USER_DENIED_CONSENT();
207 
208 // Runs func_ptr, and logs a duration report after it's finished.
209 #define RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, ...)      \
210     {                                                            \
211         DurationReporter duration_reporter_in_macro(log_title);  \
212         func_ptr(__VA_ARGS__);                                   \
213     }
214 
215 // Similar with RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK, an additional duration report
216 // is output after a slow function is finished.
217 #define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(log_title, func_ptr, ...) \
218     RETURN_IF_USER_DENIED_CONSENT();                                           \
219     RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, __VA_ARGS__);               \
220     RETURN_IF_USER_DENIED_CONSENT();
221 
222 #define WAIT_TASK_WITH_CONSENT_CHECK(future) \
223     RETURN_IF_USER_DENIED_CONSENT();                      \
224     WaitForTask(future);                     \
225     RETURN_IF_USER_DENIED_CONSENT();
226 
227 static const char* WAKE_LOCK_NAME = "dumpstate_wakelock";
228 
229 // Names of parallel tasks, they are used for the DumpPool to identify the dump
230 // task and the log title of the duration report.
231 static const std::string DUMP_TRACES_TASK = "DUMP TRACES";
232 static const std::string DUMP_INCIDENT_REPORT_TASK = "INCIDENT REPORT";
233 static const std::string DUMP_HALS_TASK = "DUMP HALS";
234 static const std::string DUMP_BOARD_TASK = "dumpstate_board()";
235 static const std::string DUMP_CHECKINS_TASK = "DUMP CHECKINS";
236 
237 namespace android {
238 namespace os {
239 namespace {
240 
Open(std::string path,int flags,mode_t mode=0)241 static int Open(std::string path, int flags, mode_t mode = 0) {
242     int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
243     if (fd == -1) {
244         MYLOGE("open(%s, %s)\n", path.c_str(), strerror(errno));
245     }
246     return fd;
247 }
248 
OpenForWrite(std::string path)249 static int OpenForWrite(std::string path) {
250     return Open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
251                 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
252 }
253 
OpenForRead(std::string path)254 static int OpenForRead(std::string path) {
255     return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
256 }
257 
CopyFile(int in_fd,int out_fd)258 bool CopyFile(int in_fd, int out_fd) {
259     char buf[4096];
260     ssize_t byte_count;
261     while ((byte_count = TEMP_FAILURE_RETRY(read(in_fd, buf, sizeof(buf)))) > 0) {
262         if (!android::base::WriteFully(out_fd, buf, byte_count)) {
263             return false;
264         }
265     }
266     return (byte_count != -1);
267 }
268 
CopyFileToFd(const std::string & input_file,int out_fd)269 static bool CopyFileToFd(const std::string& input_file, int out_fd) {
270     MYLOGD("Going to copy file (%s) to %d\n", input_file.c_str(), out_fd);
271 
272     // Obtain a handle to the source file.
273     android::base::unique_fd in_fd(OpenForRead(input_file));
274     if (out_fd != -1 && in_fd.get() != -1) {
275         if (CopyFile(in_fd.get(), out_fd)) {
276             return true;
277         }
278         MYLOGE("Failed to copy file: %s\n", strerror(errno));
279     }
280     return false;
281 }
282 
UnlinkAndLogOnError(const std::string & file)283 static bool UnlinkAndLogOnError(const std::string& file) {
284     if (file.empty()) {
285         return false;
286     }
287     if (unlink(file.c_str())) {
288         MYLOGE("Failed to unlink file (%s): %s\n", file.c_str(), strerror(errno));
289         return false;
290     }
291     return true;
292 }
293 
GetModuleMetadataVersion()294 int64_t GetModuleMetadataVersion() {
295     auto binder = defaultServiceManager()->getService(android::String16("package_native"));
296     if (binder == nullptr) {
297         MYLOGE("Failed to retrieve package_native service");
298         return 0L;
299     }
300     auto package_service = android::interface_cast<content::pm::IPackageManagerNative>(binder);
301     std::string package_name;
302     auto status = package_service->getModuleMetadataPackageName(&package_name);
303     if (!status.isOk()) {
304         MYLOGE("Failed to retrieve module metadata package name: %s", status.toString8().c_str());
305         return 0L;
306     }
307     MYLOGD("Module metadata package name: %s\n", package_name.c_str());
308     int64_t version_code;
309     status = package_service->getVersionCodeForPackage(android::String16(package_name.c_str()),
310                                                        &version_code);
311     if (!status.isOk()) {
312         MYLOGE("Failed to retrieve module metadata version: %s", status.toString8().c_str());
313         return 0L;
314     }
315     return version_code;
316 }
317 
PathExists(const std::string & path)318 static bool PathExists(const std::string& path) {
319   struct stat sb;
320   return stat(path.c_str(), &sb) == 0;
321 }
322 
CopyFileToFile(const std::string & input_file,const std::string & output_file)323 static bool CopyFileToFile(const std::string& input_file, const std::string& output_file) {
324     if (input_file == output_file) {
325         MYLOGD("Skipping copying bugreport file since the destination is the same (%s)\n",
326                output_file.c_str());
327         return false;
328     }
329     else if (PathExists(output_file)) {
330         MYLOGD("Cannot overwrite an existing file (%s)\n", output_file.c_str());
331         return false;
332     }
333 
334     MYLOGD("Going to copy bugreport file (%s) to %s\n", input_file.c_str(), output_file.c_str());
335     android::base::unique_fd out_fd(OpenForWrite(output_file));
336     return CopyFileToFd(input_file, out_fd.get());
337 }
338 
339 }  // namespace
340 }  // namespace os
341 }  // namespace android
342 
RunDumpsys(const std::string & title,const std::vector<std::string> & dumpsysArgs,const CommandOptions & options=Dumpstate::DEFAULT_DUMPSYS,long dumpsysTimeoutMs=0,int out_fd=STDOUT_FILENO)343 static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
344                        const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
345                        long dumpsysTimeoutMs = 0, int out_fd = STDOUT_FILENO) {
346     return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs, out_fd);
347 }
RunDumpsys(const std::string & title,const std::vector<std::string> & dumpsysArgs,int out_fd)348 static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
349                        int out_fd) {
350     return ds.RunDumpsys(title, dumpsysArgs, Dumpstate::DEFAULT_DUMPSYS, 0, out_fd);
351 }
DumpFile(const std::string & title,const std::string & path)352 static int DumpFile(const std::string& title, const std::string& path) {
353     return ds.DumpFile(title, path);
354 }
355 
356 // Relative directory (inside the zip) for all files copied as-is into the bugreport.
357 static const std::string ZIP_ROOT_DIR = "FS";
358 
359 static const std::string kProtoPath = "proto/";
360 static const std::string kProtoExt = ".proto";
361 static const std::string kDumpstateBoardFiles[] = {
362     "dumpstate_board.txt",
363     "dumpstate_board.bin"
364 };
365 static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
366 
367 static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
368 static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
369 
370 static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
371 
372 /*
373  * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
374  * The returned vector is sorted by the mtimes of the dumps with descending
375  * order.
376  */
GetDumpFds(const std::string & dir_path,const std::string & file_prefix)377 static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
378                                         const std::string& file_prefix) {
379     std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
380 
381     if (dump_dir == nullptr) {
382         MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno));
383         return std::vector<DumpData>();
384     }
385 
386     std::vector<DumpData> dump_data;
387     struct dirent* entry = nullptr;
388     while ((entry = readdir(dump_dir.get()))) {
389         if (entry->d_type != DT_REG) {
390             continue;
391         }
392 
393         const std::string base_name(entry->d_name);
394         if (base_name.find(file_prefix) != 0) {
395             continue;
396         }
397 
398         const std::string abs_path = dir_path + base_name;
399         android::base::unique_fd fd(
400             TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
401         if (fd == -1) {
402             MYLOGW("Unable to open dump file %s: %s\n", abs_path.c_str(), strerror(errno));
403             break;
404         }
405 
406         struct stat st = {};
407         if (fstat(fd, &st) == -1) {
408             MYLOGW("Unable to stat dump file %s: %s\n", abs_path.c_str(), strerror(errno));
409             continue;
410         }
411 
412         dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
413     }
414     if (!dump_data.empty()) {
415         std::sort(dump_data.begin(), dump_data.end(),
416             [](const auto& a, const auto& b) { return a.mtime > b.mtime; });
417     }
418 
419     return dump_data;
420 }
421 
AddDumps(const std::vector<DumpData>::const_iterator start,const std::vector<DumpData>::const_iterator end,const char * type_name,const bool add_to_zip)422 static bool AddDumps(const std::vector<DumpData>::const_iterator start,
423                      const std::vector<DumpData>::const_iterator end,
424                      const char* type_name, const bool add_to_zip) {
425     bool dumped = false;
426     for (auto it = start; it != end; ++it) {
427         const std::string& name = it->name;
428         const int fd = it->fd;
429         dumped = true;
430 
431         // Seek to the beginning of the file before dumping any data. A given
432         // DumpData entry might be dumped multiple times in the report.
433         //
434         // For example, the most recent ANR entry is dumped to the body of the
435         // main entry and it also shows up as a separate entry in the bugreport
436         // ZIP file.
437         if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) {
438             MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(),
439                    strerror(errno));
440         }
441 
442         if (add_to_zip) {
443             if (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd, /* timeout = */ 0ms) != OK) {
444                 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
445             }
446         } else {
447             dump_file_from_fd(type_name, name.c_str(), fd);
448         }
449     }
450 
451     return dumped;
452 }
453 
454 // for_each_pid() callback to get mount info about a process.
do_mountinfo(int pid,const char * name)455 void do_mountinfo(int pid, const char* name __attribute__((unused))) {
456     char path[PATH_MAX];
457 
458     // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
459     // are added.
460     snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
461     char linkname[PATH_MAX];
462     ssize_t r = readlink(path, linkname, PATH_MAX);
463     if (r == -1) {
464         MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
465         return;
466     }
467     linkname[r] = '\0';
468 
469     if (mount_points.find(linkname) == mount_points.end()) {
470         // First time this mount point was found: add it
471         snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
472         if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
473             mount_points.insert(linkname);
474         } else {
475             MYLOGE("Unable to add mountinfo %s to zip file\n", path);
476         }
477     }
478 }
479 
add_mountinfo()480 void add_mountinfo() {
481     std::string title = "MOUNT INFO";
482     mount_points.clear();
483     DurationReporter duration_reporter(title, true);
484     for_each_pid(do_mountinfo, nullptr);
485     MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
486 }
487 
dump_dev_files(const char * title,const char * driverpath,const char * filename)488 static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
489 {
490     DIR *d;
491     struct dirent *de;
492     char path[PATH_MAX];
493 
494     d = opendir(driverpath);
495     if (d == nullptr) {
496         return;
497     }
498 
499     while ((de = readdir(d))) {
500         if (de->d_type != DT_LNK) {
501             continue;
502         }
503         snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
504         DumpFile(title, path);
505     }
506 
507     closedir(d);
508 }
509 
skip_not_stat(const char * path)510 static bool skip_not_stat(const char *path) {
511     static const char stat[] = "/stat";
512     size_t len = strlen(path);
513     if (path[len - 1] == '/') { /* Directory? */
514         return false;
515     }
516     return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
517 }
518 
skip_none(const char * path)519 static bool skip_none(const char* path __attribute__((unused))) {
520     return false;
521 }
522 
523 unsigned long worst_write_perf = 20000; /* in KB/s */
524 
525 //
526 //  stat offsets
527 // Name            units         description
528 // ----            -----         -----------
529 // read I/Os       requests      number of read I/Os processed
530 #define __STAT_READ_IOS      0
531 // read merges     requests      number of read I/Os merged with in-queue I/O
532 #define __STAT_READ_MERGES   1
533 // read sectors    sectors       number of sectors read
534 #define __STAT_READ_SECTORS  2
535 // read ticks      milliseconds  total wait time for read requests
536 #define __STAT_READ_TICKS    3
537 // write I/Os      requests      number of write I/Os processed
538 #define __STAT_WRITE_IOS     4
539 // write merges    requests      number of write I/Os merged with in-queue I/O
540 #define __STAT_WRITE_MERGES  5
541 // write sectors   sectors       number of sectors written
542 #define __STAT_WRITE_SECTORS 6
543 // write ticks     milliseconds  total wait time for write requests
544 #define __STAT_WRITE_TICKS   7
545 // in_flight       requests      number of I/Os currently in flight
546 #define __STAT_IN_FLIGHT     8
547 // io_ticks        milliseconds  total time this block device has been active
548 #define __STAT_IO_TICKS      9
549 // time_in_queue   milliseconds  total wait time for all requests
550 #define __STAT_IN_QUEUE     10
551 #define __STAT_NUMBER_FIELD 11
552 //
553 // read I/Os, write I/Os
554 // =====================
555 //
556 // These values increment when an I/O request completes.
557 //
558 // read merges, write merges
559 // =========================
560 //
561 // These values increment when an I/O request is merged with an
562 // already-queued I/O request.
563 //
564 // read sectors, write sectors
565 // ===========================
566 //
567 // These values count the number of sectors read from or written to this
568 // block device.  The "sectors" in question are the standard UNIX 512-byte
569 // sectors, not any device- or filesystem-specific block size.  The
570 // counters are incremented when the I/O completes.
571 #define SECTOR_SIZE 512
572 //
573 // read ticks, write ticks
574 // =======================
575 //
576 // These values count the number of milliseconds that I/O requests have
577 // waited on this block device.  If there are multiple I/O requests waiting,
578 // these values will increase at a rate greater than 1000/second; for
579 // example, if 60 read requests wait for an average of 30 ms, the read_ticks
580 // field will increase by 60*30 = 1800.
581 //
582 // in_flight
583 // =========
584 //
585 // This value counts the number of I/O requests that have been issued to
586 // the device driver but have not yet completed.  It does not include I/O
587 // requests that are in the queue but not yet issued to the device driver.
588 //
589 // io_ticks
590 // ========
591 //
592 // This value counts the number of milliseconds during which the device has
593 // had I/O requests queued.
594 //
595 // time_in_queue
596 // =============
597 //
598 // This value counts the number of milliseconds that I/O requests have waited
599 // on this block device.  If there are multiple I/O requests waiting, this
600 // value will increase as the product of the number of milliseconds times the
601 // number of requests waiting (see "read ticks" above for an example).
602 #define S_TO_MS 1000
603 //
604 
dump_stat_from_fd(const char * title __unused,const char * path,int fd)605 static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
606     unsigned long long fields[__STAT_NUMBER_FIELD];
607     bool z;
608     char *cp, *buffer = nullptr;
609     size_t i = 0;
610     FILE *fp = fdopen(dup(fd), "rb");
611     getline(&buffer, &i, fp);
612     fclose(fp);
613     if (!buffer) {
614         return -errno;
615     }
616     i = strlen(buffer);
617     while ((i > 0) && (buffer[i - 1] == '\n')) {
618         buffer[--i] = '\0';
619     }
620     if (!*buffer) {
621         free(buffer);
622         return 0;
623     }
624     z = true;
625     for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
626         fields[i] = strtoull(cp, &cp, 10);
627         if (fields[i] != 0) {
628             z = false;
629         }
630     }
631     if (z) { /* never accessed */
632         free(buffer);
633         return 0;
634     }
635 
636     if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
637         path += sizeof(BLK_DEV_SYS_DIR) - 1;
638     }
639 
640     printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
641            "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
642            "W-wait", "in-fli", "activ", "T-wait", path, buffer);
643     free(buffer);
644 
645     if (fields[__STAT_IO_TICKS]) {
646         unsigned long read_perf = 0;
647         unsigned long read_ios = 0;
648         if (fields[__STAT_READ_TICKS]) {
649             unsigned long long divisor = fields[__STAT_READ_TICKS]
650                                        * fields[__STAT_IO_TICKS];
651             read_perf = ((unsigned long long)SECTOR_SIZE
652                            * fields[__STAT_READ_SECTORS]
653                            * fields[__STAT_IN_QUEUE] + (divisor >> 1))
654                                         / divisor;
655             read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
656                            * fields[__STAT_IN_QUEUE] + (divisor >> 1))
657                                         / divisor;
658         }
659 
660         unsigned long write_perf = 0;
661         unsigned long write_ios = 0;
662         if (fields[__STAT_WRITE_TICKS]) {
663             unsigned long long divisor = fields[__STAT_WRITE_TICKS]
664                                        * fields[__STAT_IO_TICKS];
665             write_perf = ((unsigned long long)SECTOR_SIZE
666                            * fields[__STAT_WRITE_SECTORS]
667                            * fields[__STAT_IN_QUEUE] + (divisor >> 1))
668                                         / divisor;
669             write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
670                            * fields[__STAT_IN_QUEUE] + (divisor >> 1))
671                                         / divisor;
672         }
673 
674         unsigned queue = (fields[__STAT_IN_QUEUE]
675                              + (fields[__STAT_IO_TICKS] >> 1))
676                                  / fields[__STAT_IO_TICKS];
677 
678         if (!write_perf && !write_ios) {
679             printf("%-30s: perf(ios) rd: %luKB/s(%lu/s) q: %u\n", path, read_perf, read_ios, queue);
680         } else {
681             printf("%-30s: perf(ios) rd: %luKB/s(%lu/s) wr: %luKB/s(%lu/s) q: %u\n", path, read_perf,
682                    read_ios, write_perf, write_ios, queue);
683         }
684 
685         /* bugreport timeout factor adjustment */
686         if ((write_perf > 1) && (write_perf < worst_write_perf)) {
687             worst_write_perf = write_perf;
688         }
689     }
690     return 0;
691 }
692 
693 static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
694 
695 // Returns the actual readable size of the given buffer or -1 on error.
logcat_buffer_readable_size(const std::string & buffer)696 static long logcat_buffer_readable_size(const std::string& buffer) {
697     std::unique_ptr<logger_list, decltype(&android_logger_list_free)> logger_list{
698         android_logger_list_alloc(0, 0, 0), &android_logger_list_free};
699     auto logger = android_logger_open(logger_list.get(), android_name_to_log_id(buffer.c_str()));
700 
701     return android_logger_get_log_readable_size(logger);
702 }
703 
704 // Returns timeout in ms to read a list of buffers.
logcat_timeout(const std::vector<std::string> & buffers)705 static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
706     unsigned long timeout_ms = 0;
707     for (const auto& buffer : buffers) {
708         long readable_size = logcat_buffer_readable_size(buffer);
709         if (readable_size > 0) {
710             // Engineering margin is ten-fold our guess.
711             timeout_ms += 10 * (readable_size + worst_write_perf) / worst_write_perf;
712         }
713     }
714     return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
715 }
716 
717 // Opens a socket and returns its file descriptor.
718 static int open_socket(const char* service);
719 
ConsentCallback()720 Dumpstate::ConsentCallback::ConsentCallback() : result_(UNAVAILABLE), start_time_(Nanotime()) {
721 }
722 
onReportApproved()723 android::binder::Status Dumpstate::ConsentCallback::onReportApproved() {
724     std::lock_guard<std::mutex> lock(lock_);
725     result_ = APPROVED;
726     MYLOGD("User approved consent to share bugreport\n");
727 
728     // Maybe copy screenshot so calling app can display the screenshot to the user as soon as
729     // consent is granted.
730     if (ds.options_->is_screenshot_copied) {
731         return android::binder::Status::ok();
732     }
733 
734     if (!ds.options_->do_screenshot || ds.options_->screenshot_fd.get() == -1 ||
735         !ds.do_early_screenshot_) {
736         return android::binder::Status::ok();
737     }
738 
739     bool copy_succeeded = android::os::CopyFileToFd(ds.screenshot_path_,
740                                                     ds.options_->screenshot_fd.get());
741     ds.options_->is_screenshot_copied = copy_succeeded;
742     if (copy_succeeded) {
743         android::os::UnlinkAndLogOnError(ds.screenshot_path_);
744     }
745     return android::binder::Status::ok();
746 }
747 
onReportDenied()748 android::binder::Status Dumpstate::ConsentCallback::onReportDenied() {
749     std::lock_guard<std::mutex> lock(lock_);
750     result_ = DENIED;
751     MYLOGW("User denied consent to share bugreport\n");
752     return android::binder::Status::ok();
753 }
754 
getResult()755 UserConsentResult Dumpstate::ConsentCallback::getResult() {
756     std::lock_guard<std::mutex> lock(lock_);
757     return result_;
758 }
759 
getElapsedTimeMs() const760 uint64_t Dumpstate::ConsentCallback::getElapsedTimeMs() const {
761     return (Nanotime() - start_time_) / NANOS_PER_MILLI;
762 }
763 
PrintHeader() const764 void Dumpstate::PrintHeader() const {
765     std::string build, fingerprint, radio, bootloader, network;
766     char date[80];
767 
768     build = android::base::GetProperty("ro.build.display.id", "(unknown)");
769     fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
770     radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
771     bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
772     network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
773     strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
774 
775     printf("========================================================\n");
776     printf("== dumpstate: %s\n", date);
777     printf("========================================================\n");
778 
779     printf("\n");
780     printf("Build: %s\n", build.c_str());
781     // NOTE: fingerprint entry format is important for other tools.
782     printf("Build fingerprint: '%s'\n", fingerprint.c_str());
783     printf("Bootloader: %s\n", bootloader.c_str());
784     printf("Radio: %s\n", radio.c_str());
785     printf("Network: %s\n", network.c_str());
786     int64_t module_metadata_version = android::os::GetModuleMetadataVersion();
787     if (module_metadata_version != 0) {
788         printf("Module Metadata version: %" PRId64 "\n", module_metadata_version);
789     }
790     printf("SDK extension versions [r=%s s=%s]\n",
791            android::base::GetProperty("build.version.extensions.r", "-").c_str(),
792            android::base::GetProperty("build.version.extensions.s", "-").c_str());
793 
794     printf("Kernel: ");
795     DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
796     printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
797     printf("Uptime: ");
798     RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"},
799                    CommandOptions::WithTimeout(1).Always().Build());
800     printf("Bugreport format version: %s\n", version_.c_str());
801     printf("Dumpstate info: id=%d pid=%d dry_run=%d parallel_run=%d args=%s bugreport_mode=%s\n",
802            id_, pid_, PropertiesHelper::IsDryRun(), PropertiesHelper::IsParallelRun(),
803            options_->args.c_str(), options_->bugreport_mode_string.c_str());
804     printf("\n");
805 }
806 
807 // List of file extensions that can cause a zip file attachment to be rejected by some email
808 // service providers.
809 static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
810       ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
811       ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
812       ".shb", ".sys", ".vb",  ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
813 };
814 
AddZipEntryFromFd(const std::string & entry_name,int fd,std::chrono::milliseconds timeout=0ms)815 status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd,
816                                       std::chrono::milliseconds timeout = 0ms) {
817     std::string valid_name = entry_name;
818 
819     // Rename extension if necessary.
820     size_t idx = entry_name.rfind('.');
821     if (idx != std::string::npos) {
822         std::string extension = entry_name.substr(idx);
823         std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
824         if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
825             valid_name = entry_name + ".renamed";
826             MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
827         }
828     }
829 
830     // Logging statement  below is useful to time how long each entry takes, but it's too verbose.
831     // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
832     int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), ZipWriter::kCompress,
833                                                   get_mtime(fd, ds.now_));
834     if (err != 0) {
835         MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
836                ZipWriter::ErrorCodeString(err));
837         return UNKNOWN_ERROR;
838     }
839     bool finished_entry = false;
840     auto finish_entry = [this, &finished_entry] {
841         if (!finished_entry) {
842             // This should only be called when we're going to return an earlier error,
843             // which would've been logged. This may imply the file is already corrupt
844             // and any further logging from FinishEntry is more likely to mislead than
845             // not.
846             this->zip_writer_->FinishEntry();
847         }
848     };
849     auto scope_guard = android::base::make_scope_guard(finish_entry);
850     auto start = std::chrono::steady_clock::now();
851     auto end = start + timeout;
852     struct pollfd pfd = {fd, POLLIN};
853 
854     std::vector<uint8_t> buffer(65536);
855     while (1) {
856         if (timeout.count() > 0) {
857             // lambda to recalculate the timeout.
858             auto time_left_ms = [end]() {
859                 auto now = std::chrono::steady_clock::now();
860                 auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
861                 return std::max(diff.count(), 0LL);
862             };
863 
864             int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
865             if (rc < 0) {
866                 MYLOGE("Error in poll while adding from fd to zip entry %s:%s\n",
867                        entry_name.c_str(), strerror(errno));
868                 return -errno;
869             } else if (rc == 0) {
870                 MYLOGE("Timed out adding from fd to zip entry %s:%s Timeout:%lldms\n",
871                        entry_name.c_str(), strerror(errno), timeout.count());
872                 return TIMED_OUT;
873             }
874         }
875 
876         ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
877         if (bytes_read == 0) {
878             break;
879         } else if (bytes_read == -1) {
880             MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
881             return -errno;
882         }
883         err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
884         if (err) {
885             MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
886             return UNKNOWN_ERROR;
887         }
888     }
889 
890     err = zip_writer_->FinishEntry();
891     finished_entry = true;
892     if (err != 0) {
893         MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
894         return UNKNOWN_ERROR;
895     }
896 
897     return OK;
898 }
899 
AddZipEntry(const std::string & entry_name,const std::string & entry_path)900 bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
901     android::base::unique_fd fd(
902         TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
903     if (fd == -1) {
904         MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
905         return false;
906     }
907 
908     return (AddZipEntryFromFd(entry_name, fd.get()) == OK);
909 }
910 
911 /* adds a file to the existing zipped bugreport */
_add_file_from_fd(const char * title,const char * path,int fd)912 static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
913     return (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) == OK) ? 0 : 1;
914 }
915 
AddDir(const std::string & dir,bool recursive)916 void Dumpstate::AddDir(const std::string& dir, bool recursive) {
917     MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
918     DurationReporter duration_reporter(dir, true);
919     dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
920 }
921 
AddTextZipEntry(const std::string & entry_name,const std::string & content)922 bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
923     MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
924     int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, ds.now_);
925     if (err != 0) {
926         MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
927                ZipWriter::ErrorCodeString(err));
928         return false;
929     }
930 
931     err = zip_writer_->WriteBytes(content.c_str(), content.length());
932     if (err != 0) {
933         MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
934                ZipWriter::ErrorCodeString(err));
935         return false;
936     }
937 
938     err = zip_writer_->FinishEntry();
939     if (err != 0) {
940         MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
941         return false;
942     }
943 
944     return true;
945 }
946 
DoKmsg()947 static void DoKmsg() {
948     struct stat st;
949     if (!stat(PSTORE_LAST_KMSG, &st)) {
950         /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
951         DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
952     } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
953         DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
954     } else {
955         /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
956         DumpFile("LAST KMSG", "/proc/last_kmsg");
957     }
958 }
959 
DoKernelLogcat()960 static void DoKernelLogcat() {
961     unsigned long timeout_ms = logcat_timeout({"kernel"});
962     RunCommand(
963         "KERNEL LOG",
964         {"logcat", "-b", "kernel", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
965         CommandOptions::WithTimeoutInMs(timeout_ms).Build());
966 }
967 
DoSystemLogcat(time_t since)968 static void DoSystemLogcat(time_t since) {
969     char since_str[80];
970     strftime(since_str, sizeof(since_str), "%Y-%m-%d %H:%M:%S.000", localtime(&since));
971 
972     unsigned long timeout_ms = logcat_timeout({"main", "system", "crash"});
973     RunCommand("SYSTEM LOG",
974                {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v", "-T",
975                 since_str},
976                CommandOptions::WithTimeoutInMs(timeout_ms).Build());
977 }
978 
DoRadioLogcat()979 static void DoRadioLogcat() {
980     unsigned long timeout_ms = logcat_timeout({"radio"});
981     RunCommand(
982         "RADIO LOG",
983         {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
984         CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
985 }
986 
DoLogcat()987 static void DoLogcat() {
988     unsigned long timeout_ms;
989     // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
990     // calculate timeout
991     timeout_ms = logcat_timeout({"main", "system", "crash"});
992     RunCommand("SYSTEM LOG",
993                {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
994                CommandOptions::WithTimeoutInMs(timeout_ms).Build());
995     timeout_ms = logcat_timeout({"events"});
996     RunCommand(
997         "EVENT LOG",
998         {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
999         CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
1000     timeout_ms = logcat_timeout({"stats"});
1001     RunCommand(
1002         "STATS LOG",
1003         {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1004         CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
1005     DoRadioLogcat();
1006 
1007     RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
1008 
1009     /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
1010     RunCommand("LAST LOGCAT", {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable",
1011                                "-v", "uid", "-d", "*:v"});
1012 }
1013 
DumpIncidentReport()1014 static void DumpIncidentReport() {
1015     const std::string path = ds.bugreport_internal_dir_ + "/tmp_incident_report";
1016     auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1017                 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1018                 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1019     if (fd < 0) {
1020         MYLOGE("Could not open %s to dump incident report.\n", path.c_str());
1021         return;
1022     }
1023     RunCommandToFd(fd, "", {"incident", "-u"}, CommandOptions::WithTimeout(120).Build());
1024     bool empty = 0 == lseek(fd, 0, SEEK_END);
1025     if (!empty) {
1026         // Use a different name from "incident.proto"
1027         // /proto/incident.proto is reserved for incident service dump
1028         // i.e. metadata for debugging.
1029         ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "incident_report" + kProtoExt,
1030                 path);
1031     } else {
1032         unlink(path.c_str());
1033     }
1034 }
1035 
MaybeAddSystemTraceToZip()1036 static void MaybeAddSystemTraceToZip() {
1037     // This function copies into the .zip the system trace that was snapshotted
1038     // by the early call to MaybeSnapshotSystemTrace(), if any background
1039     // tracing was happening.
1040     if (!ds.has_system_trace_) {
1041         // No background trace was happening at the time dumpstate was invoked.
1042         return;
1043     }
1044     ds.AddZipEntry(
1045             ZIP_ROOT_DIR + SYSTEM_TRACE_SNAPSHOT,
1046             SYSTEM_TRACE_SNAPSHOT);
1047     android::os::UnlinkAndLogOnError(SYSTEM_TRACE_SNAPSHOT);
1048 }
1049 
DumpVisibleWindowViews()1050 static void DumpVisibleWindowViews() {
1051     DurationReporter duration_reporter("VISIBLE WINDOW VIEWS");
1052     const std::string path = ds.bugreport_internal_dir_ + "/tmp_visible_window_views";
1053     auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1054                 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1055                 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1056     if (fd < 0) {
1057         MYLOGE("Could not open %s to dump visible views.\n", path.c_str());
1058         return;
1059     }
1060     RunCommandToFd(fd, "", {"cmd", "window", "dump-visible-window-views"},
1061                    CommandOptions::WithTimeout(120).Build());
1062     bool empty = 0 == lseek(fd, 0, SEEK_END);
1063     if (!empty) {
1064         ds.AddZipEntry("visible_windows.zip", path);
1065     } else {
1066         MYLOGW("Failed to dump visible windows\n");
1067     }
1068     unlink(path.c_str());
1069 }
1070 
DumpIpTablesAsRoot()1071 static void DumpIpTablesAsRoot() {
1072     RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
1073     RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
1074     RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
1075     /* no ip6 nat */
1076     RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
1077     RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
1078     RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
1079     RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
1080 }
1081 
DumpDynamicPartitionInfo()1082 static void DumpDynamicPartitionInfo() {
1083     if (!::android::base::GetBoolProperty("ro.boot.dynamic_partitions", false)) {
1084         return;
1085     }
1086 
1087     RunCommand("LPDUMP", {"lpdump", "--all"});
1088     RunCommand("DEVICE-MAPPER", {"gsid", "dump-device-mapper"});
1089 }
1090 
AddAnrTraceDir(const std::string & anr_traces_dir)1091 static void AddAnrTraceDir(const std::string& anr_traces_dir) {
1092     MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
1093            anr_traces_dir.c_str());
1094 
1095     // If we're here, dump_traces_path will always be a temporary file
1096     // (created with mkostemp or similar) that contains dumps taken earlier
1097     // on in the process.
1098     if (dump_traces_path != nullptr) {
1099         MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
1100                 dump_traces_path);
1101         ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
1102 
1103         const int ret = unlink(dump_traces_path);
1104         if (ret == -1) {
1105             MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
1106                    strerror(errno));
1107         }
1108     }
1109 
1110     // Add a specific message for the first ANR Dump.
1111     if (ds.anr_data_.size() > 0) {
1112         // The "last" ANR will always be present in the body of the main entry.
1113         AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1,
1114                  "VM TRACES AT LAST ANR", false /* add_to_zip */);
1115 
1116         // Historical ANRs are always included as separate entries in the bugreport zip file.
1117         AddDumps(ds.anr_data_.begin(), ds.anr_data_.end(),
1118                  "HISTORICAL ANR", true /* add_to_zip */);
1119     } else {
1120         printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
1121     }
1122 }
1123 
AddAnrTraceFiles()1124 static void AddAnrTraceFiles() {
1125     std::string anr_traces_dir = "/data/anr";
1126 
1127     AddAnrTraceDir(anr_traces_dir);
1128 
1129     RunCommand("ANR FILES", {"ls", "-lt", ANR_DIR});
1130 
1131     // Slow traces for slow operations.
1132     struct stat st;
1133     int i = 0;
1134     while (true) {
1135         const std::string slow_trace_path =
1136             anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
1137         if (stat(slow_trace_path.c_str(), &st)) {
1138             // No traces file at this index, done with the files.
1139             break;
1140         }
1141         ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
1142         i++;
1143     }
1144 }
1145 
DumpBlockStatFiles()1146 static void DumpBlockStatFiles() {
1147     DurationReporter duration_reporter("DUMP BLOCK STAT");
1148 
1149     std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
1150 
1151     if (dirptr == nullptr) {
1152         MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1153         return;
1154     }
1155 
1156     printf("------ DUMP BLOCK STAT ------\n\n");
1157     while (struct dirent *d = readdir(dirptr.get())) {
1158         if ((d->d_name[0] == '.')
1159          && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1160           || (d->d_name[1] == '\0'))) {
1161             continue;
1162         }
1163         const std::string new_path =
1164             android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1165         printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1166         dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1167         printf("\n");
1168     }
1169      return;
1170 }
1171 
DumpPacketStats()1172 static void DumpPacketStats() {
1173     DumpFile("NETWORK DEV INFO", "/proc/net/dev");
1174 }
1175 
DumpIpAddrAndRules()1176 static void DumpIpAddrAndRules() {
1177     /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
1178     RunCommand("NETWORK INTERFACES", {"ip", "link"});
1179     RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1180     RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1181     RunCommand("IP RULES", {"ip", "rule", "show"});
1182     RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1183 }
1184 
RunDumpsysTextByPriority(const std::string & title,int priority,std::chrono::milliseconds timeout,std::chrono::milliseconds service_timeout)1185 static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, int priority,
1186                                                      std::chrono::milliseconds timeout,
1187                                                      std::chrono::milliseconds service_timeout) {
1188     auto start = std::chrono::steady_clock::now();
1189     sp<android::IServiceManager> sm = defaultServiceManager();
1190     Dumpsys dumpsys(sm.get());
1191     Vector<String16> args;
1192     Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
1193     Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1194     for (const String16& service : services) {
1195         RETURN_IF_USER_DENIED_CONSENT();
1196         std::string path(title);
1197         path.append(" - ").append(String8(service).c_str());
1198         size_t bytes_written = 0;
1199         if (PropertiesHelper::IsDryRun()) {
1200              dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1201              dumpsys.writeDumpFooter(STDOUT_FILENO, service, std::chrono::milliseconds(1));
1202         } else {
1203             status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP, service, args);
1204             if (status == OK) {
1205                 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1206                 std::chrono::duration<double> elapsed_seconds;
1207                 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH &&
1208                     service == String16("meminfo")) {
1209                     // Use a longer timeout for meminfo, since 30s is not always enough.
1210                     status = dumpsys.writeDump(STDOUT_FILENO, service, 60s,
1211                                                /* as_proto = */ false, elapsed_seconds,
1212                                                 bytes_written);
1213                 } else {
1214                     status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
1215                                                /* as_proto = */ false, elapsed_seconds,
1216                                                 bytes_written);
1217                 }
1218                 dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
1219                 bool dump_complete = (status == OK);
1220                 dumpsys.stopDumpThread(dump_complete);
1221             }
1222         }
1223 
1224         auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1225             std::chrono::steady_clock::now() - start);
1226         if (elapsed_duration > timeout) {
1227             MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1228                    elapsed_duration.count());
1229             break;
1230         }
1231     }
1232     return Dumpstate::RunStatus::OK;
1233 }
1234 
RunDumpsysText(const std::string & title,int priority,std::chrono::milliseconds timeout,std::chrono::milliseconds service_timeout)1235 static void RunDumpsysText(const std::string& title, int priority,
1236                            std::chrono::milliseconds timeout,
1237                            std::chrono::milliseconds service_timeout) {
1238     DurationReporter duration_reporter(title);
1239     dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1240     fsync(STDOUT_FILENO);
1241     RunDumpsysTextByPriority(title, priority, timeout, service_timeout);
1242 }
1243 
1244 /* Dump all services registered with Normal or Default priority. */
RunDumpsysTextNormalPriority(const std::string & title,std::chrono::milliseconds timeout,std::chrono::milliseconds service_timeout)1245 static Dumpstate::RunStatus RunDumpsysTextNormalPriority(const std::string& title,
1246                                                          std::chrono::milliseconds timeout,
1247                                                          std::chrono::milliseconds service_timeout) {
1248     DurationReporter duration_reporter(title);
1249     dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1250     fsync(STDOUT_FILENO);
1251     RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout,
1252                              service_timeout);
1253 
1254     RETURN_IF_USER_DENIED_CONSENT();
1255 
1256     return RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1257                                     service_timeout);
1258 }
1259 
RunDumpsysProto(const std::string & title,int priority,std::chrono::milliseconds timeout,std::chrono::milliseconds service_timeout)1260 static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priority,
1261                                             std::chrono::milliseconds timeout,
1262                                             std::chrono::milliseconds service_timeout) {
1263     sp<android::IServiceManager> sm = defaultServiceManager();
1264     Dumpsys dumpsys(sm.get());
1265     Vector<String16> args;
1266     Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
1267     DurationReporter duration_reporter(title);
1268 
1269     auto start = std::chrono::steady_clock::now();
1270     Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
1271     for (const String16& service : services) {
1272         RETURN_IF_USER_DENIED_CONSENT();
1273         std::string path(kProtoPath);
1274         path.append(String8(service).c_str());
1275         if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
1276             path.append("_CRITICAL");
1277         } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
1278             path.append("_HIGH");
1279         }
1280         path.append(kProtoExt);
1281         status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP, service, args);
1282         if (status == OK) {
1283             status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
1284             bool dumpTerminated = (status == OK);
1285             dumpsys.stopDumpThread(dumpTerminated);
1286         }
1287         ZipWriter::FileEntry file_entry;
1288         ds.zip_writer_->GetLastEntry(&file_entry);
1289 
1290         auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1291             std::chrono::steady_clock::now() - start);
1292         if (elapsed_duration > timeout) {
1293             MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1294                    elapsed_duration.count());
1295             break;
1296         }
1297     }
1298     return Dumpstate::RunStatus::OK;
1299 }
1300 
1301 // Runs dumpsys on services that must dump first and will take less than 100ms to dump.
RunDumpsysCritical()1302 static Dumpstate::RunStatus RunDumpsysCritical() {
1303     RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1304                    /* timeout= */ 5s, /* service_timeout= */ 500ms);
1305 
1306     RETURN_IF_USER_DENIED_CONSENT();
1307 
1308     return RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1309                            /* timeout= */ 5s, /* service_timeout= */ 500ms);
1310 }
1311 
1312 // Runs dumpsys on services that must dump first but can take up to 250ms to dump.
RunDumpsysHigh()1313 static Dumpstate::RunStatus RunDumpsysHigh() {
1314     // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
1315     // high priority. Reduce timeout once they are able to dump in a shorter time or
1316     // moved to a parallel task.
1317     RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1318                    /* timeout= */ 90s, /* service_timeout= */ 30s);
1319 
1320     RETURN_IF_USER_DENIED_CONSENT();
1321 
1322     return RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1323                            /* timeout= */ 5s, /* service_timeout= */ 1s);
1324 }
1325 
1326 // Runs dumpsys on services that must dump but can take up to 10s to dump.
RunDumpsysNormal()1327 static Dumpstate::RunStatus RunDumpsysNormal() {
1328     RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
1329 
1330     RETURN_IF_USER_DENIED_CONSENT();
1331 
1332     return RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1333                            /* timeout= */ 90s, /* service_timeout= */ 10s);
1334 }
1335 
1336 /*
1337  * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1338  * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1339  * if it's not running in the parallel task.
1340  */
DumpHals(int out_fd=STDOUT_FILENO)1341 static void DumpHals(int out_fd = STDOUT_FILENO) {
1342     RunCommand("HARDWARE HALS", {"lshal", "--all", "--types=all"},
1343                CommandOptions::WithTimeout(10).AsRootIfAvailable().Build(),
1344                false, out_fd);
1345 
1346     using android::hidl::manager::V1_0::IServiceManager;
1347     using android::hardware::defaultServiceManager;
1348 
1349     sp<IServiceManager> sm = defaultServiceManager();
1350     if (sm == nullptr) {
1351         MYLOGE("Could not retrieve hwservicemanager to dump hals.\n");
1352         return;
1353     }
1354 
1355     auto ret = sm->list([&](const auto& interfaces) {
1356         for (const std::string& interface : interfaces) {
1357             std::string cleanName = interface;
1358             std::replace_if(cleanName.begin(),
1359                             cleanName.end(),
1360                             [](char c) {
1361                                 return !isalnum(c) &&
1362                                     std::string("@-_:.").find(c) == std::string::npos;
1363                             }, '_');
1364             const std::string path = ds.bugreport_internal_dir_ + "/lshal_debug_" + cleanName;
1365 
1366             bool empty = false;
1367             {
1368                 auto fd = android::base::unique_fd(
1369                     TEMP_FAILURE_RETRY(open(path.c_str(),
1370                     O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1371                     S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1372                 if (fd < 0) {
1373                     MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str());
1374                     continue;
1375                 }
1376                 RunCommandToFd(fd,
1377                         "",
1378                         {"lshal", "debug", "-E", interface},
1379                         CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1380 
1381                 empty = 0 == lseek(fd, 0, SEEK_END);
1382             }
1383             if (!empty) {
1384                 ds.EnqueueAddZipEntryAndCleanupIfNeeded("lshal-debug/" + cleanName + ".txt",
1385                         path);
1386             } else {
1387                 unlink(path.c_str());
1388             }
1389         }
1390     });
1391 
1392     if (!ret.isOk()) {
1393         MYLOGE("Could not list hals from hwservicemanager.\n");
1394     }
1395 }
1396 
DumpExternalFragmentationInfo()1397 static void DumpExternalFragmentationInfo() {
1398     struct stat st;
1399     if (stat("/proc/buddyinfo", &st) != 0) {
1400         MYLOGE("Unable to dump external fragmentation info\n");
1401         return;
1402     }
1403 
1404     printf("------ EXTERNAL FRAGMENTATION INFO ------\n");
1405     std::ifstream ifs("/proc/buddyinfo");
1406     auto unusable_index_regex = std::regex{"Node\\s+([0-9]+),\\s+zone\\s+(\\S+)\\s+(.*)"};
1407     for (std::string line; std::getline(ifs, line);) {
1408         std::smatch match_results;
1409         if (std::regex_match(line, match_results, unusable_index_regex)) {
1410             std::stringstream free_pages(std::string{match_results[3]});
1411             std::vector<int> free_pages_per_order(std::istream_iterator<int>{free_pages},
1412                                                   std::istream_iterator<int>());
1413 
1414             int total_free_pages = 0;
1415             for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1416                 total_free_pages += (free_pages_per_order[i] * std::pow(2, i));
1417             }
1418 
1419             printf("Node %s, zone %8s", match_results[1].str().c_str(),
1420                    match_results[2].str().c_str());
1421 
1422             int usable_free_pages = total_free_pages;
1423             for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1424                 auto unusable_index = (total_free_pages - usable_free_pages) /
1425                         static_cast<double>(total_free_pages);
1426                 printf(" %5.3f", unusable_index);
1427                 usable_free_pages -= (free_pages_per_order[i] * std::pow(2, i));
1428             }
1429 
1430             printf("\n");
1431         }
1432     }
1433     printf("\n");
1434 }
1435 
DumpstateLimitedOnly()1436 static void DumpstateLimitedOnly() {
1437     // Trimmed-down version of dumpstate to only include a whitelisted
1438     // set of logs (system log, event log, and system server / system app
1439     // crashes, and networking logs). See b/136273873 and b/138459828
1440     // for context.
1441     DurationReporter duration_reporter("DUMPSTATE");
1442     unsigned long timeout_ms;
1443     // calculate timeout
1444     timeout_ms = logcat_timeout({"main", "system", "crash"});
1445     RunCommand("SYSTEM LOG",
1446                {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1447                CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1448     timeout_ms = logcat_timeout({"events"});
1449     RunCommand(
1450         "EVENT LOG",
1451         {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1452         CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1453 
1454     printf("========================================================\n");
1455     printf("== Networking Service\n");
1456     printf("========================================================\n");
1457 
1458     RunDumpsys("DUMPSYS NETWORK_SERVICE_LIMITED", {"wifi", "-a"},
1459                CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
1460     RunDumpsys("DUMPSYS CONNECTIVITY REQUESTS", {"connectivity", "requests"},
1461                CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
1462 
1463     printf("========================================================\n");
1464     printf("== Dropbox crashes\n");
1465     printf("========================================================\n");
1466 
1467     RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1468     RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1469 
1470     printf("========================================================\n");
1471     printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1472            ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1473     printf("========================================================\n");
1474     printf("== dumpstate: done (id %d)\n", ds.id_);
1475     printf("========================================================\n");
1476 }
1477 
1478 /*
1479  * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1480  * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1481  * if it's not running in the parallel task.
1482  */
DumpCheckins(int out_fd=STDOUT_FILENO)1483 static void DumpCheckins(int out_fd = STDOUT_FILENO) {
1484     dprintf(out_fd, "========================================================\n");
1485     dprintf(out_fd, "== Checkins\n");
1486     dprintf(out_fd, "========================================================\n");
1487 
1488     RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"}, out_fd);
1489     RunDumpsys("CHECKIN MEMINFO", {"meminfo", "--checkin"}, out_fd);
1490     RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"}, out_fd);
1491     RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"}, out_fd);
1492     RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"}, out_fd);
1493     RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"}, out_fd);
1494 }
1495 
1496 /*
1497  * Runs dumpsys on activity service to dump all application activities, services
1498  * and providers in the device.
1499  *
1500  * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1501  * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1502  * if it's not running in the parallel task.
1503  */
DumpAppInfos(int out_fd=STDOUT_FILENO)1504 static void DumpAppInfos(int out_fd = STDOUT_FILENO) {
1505     dprintf(out_fd, "========================================================\n");
1506     dprintf(out_fd, "== Running Application Activities\n");
1507     dprintf(out_fd, "========================================================\n");
1508 
1509     // The following dumpsys internally collects output from running apps, so it can take a long
1510     // time. So let's extend the timeout.
1511 
1512     const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1513 
1514     RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1515 
1516     dprintf(out_fd, "========================================================\n");
1517     dprintf(out_fd, "== Running Application Services (platform)\n");
1518     dprintf(out_fd, "========================================================\n");
1519 
1520     RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
1521             DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1522 
1523     dprintf(out_fd, "========================================================\n");
1524     dprintf(out_fd, "== Running Application Services (non-platform)\n");
1525     dprintf(out_fd, "========================================================\n");
1526 
1527     RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1528             DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1529 
1530     dprintf(out_fd, "========================================================\n");
1531     dprintf(out_fd, "== Running Application Providers (platform)\n");
1532     dprintf(out_fd, "========================================================\n");
1533 
1534     RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
1535             DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1536 
1537     dprintf(out_fd, "========================================================\n");
1538     dprintf(out_fd, "== Running Application Providers (non-platform)\n");
1539     dprintf(out_fd, "========================================================\n");
1540 
1541     RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1542             DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1543 }
1544 
1545 // Dumps various things. Returns early with status USER_CONSENT_DENIED if user denies consent
1546 // via the consent they are shown. Ignores other errors that occur while running various
1547 // commands. The consent checking is currently done around long running tasks, which happen to
1548 // be distributed fairly evenly throughout the function.
dumpstate()1549 static Dumpstate::RunStatus dumpstate() {
1550     DurationReporter duration_reporter("DUMPSTATE");
1551 
1552     // Enqueue slow functions into the thread pool, if the parallel run is enabled.
1553     std::future<std::string> dump_hals, dump_incident_report, dump_board, dump_checkins;
1554     if (ds.dump_pool_) {
1555         // Pool was shutdown in DumpstateDefaultAfterCritical method in order to
1556         // drop root user. Restarts it with two threads for the parallel run.
1557         ds.dump_pool_->start(/* thread_counts = */2);
1558 
1559         dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
1560         dump_incident_report = ds.dump_pool_->enqueueTask(
1561             DUMP_INCIDENT_REPORT_TASK, &DumpIncidentReport);
1562         dump_board = ds.dump_pool_->enqueueTaskWithFd(
1563             DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
1564         dump_checkins = ds.dump_pool_->enqueueTaskWithFd(DUMP_CHECKINS_TASK, &DumpCheckins, _1);
1565     }
1566 
1567     // Dump various things. Note that anything that takes "long" (i.e. several seconds) should
1568     // check intermittently (if it's intrerruptable like a foreach on pids) and/or should be wrapped
1569     // in a consent check (via RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK).
1570     dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
1571     RunCommand("UPTIME", {"uptime"});
1572     DumpBlockStatFiles();
1573     DumpFile("MEMORY INFO", "/proc/meminfo");
1574     RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
1575                             "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
1576 
1577     RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "PROCRANK", {"procrank"}, AS_ROOT_20);
1578 
1579     RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpVisibleWindowViews);
1580 
1581     DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1582     DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1583     DumpFile("SLAB INFO", "/proc/slabinfo");
1584     DumpFile("ZONEINFO", "/proc/zoneinfo");
1585     DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1586     DumpFile("BUDDYINFO", "/proc/buddyinfo");
1587     DumpExternalFragmentationInfo();
1588 
1589     DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
1590 
1591     RunCommand("PROCESSES AND THREADS",
1592                {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
1593 
1594     RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "LIBRANK", {"librank"},
1595                                          CommandOptions::AS_ROOT);
1596 
1597     if (ds.dump_pool_) {
1598         WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_hals));
1599     } else {
1600         RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_HALS_TASK, DumpHals);
1601     }
1602 
1603     RunCommand("PRINTENV", {"printenv"});
1604     RunCommand("NETSTAT", {"netstat", "-nW"});
1605     struct stat s;
1606     if (stat("/proc/modules", &s) != 0) {
1607         MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1608     } else {
1609         RunCommand("LSMOD", {"lsmod"});
1610         RunCommand("MODULES INFO",
1611                    {"sh", "-c", "cat /proc/modules | cut -d' ' -f1 | "
1612                     "    while read MOD ; do echo modinfo:$MOD ; modinfo $MOD ; "
1613                     "done"}, CommandOptions::AS_ROOT);
1614     }
1615 
1616     if (android::base::GetBoolProperty("ro.logd.kernel", false)) {
1617         DoKernelLogcat();
1618     } else {
1619         do_dmesg();
1620     }
1621 
1622     RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
1623 
1624     RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(for_each_pid, do_showmap, "SMAPS OF ALL PROCESSES");
1625 
1626     for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
1627     for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
1628 
1629     /* Dump Nfc NCI logs */
1630     ds.AddDir("/data/misc/nfc/logs", true);
1631 
1632     if (ds.options_->do_screenshot && !ds.do_early_screenshot_) {
1633         MYLOGI("taking late screenshot\n");
1634         ds.TakeScreenshot();
1635     }
1636 
1637     AddAnrTraceFiles();
1638 
1639     MaybeAddSystemTraceToZip();
1640 
1641     // NOTE: tombstones are always added as separate entries in the zip archive
1642     // and are not interspersed with the main report.
1643     const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
1644                                             "TOMBSTONE", true /* add_to_zip */);
1645     if (!tombstones_dumped) {
1646         printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
1647     }
1648 
1649     DumpPacketStats();
1650 
1651     RunDumpsys("EBPF MAP STATS", {"connectivity", "trafficcontroller"});
1652 
1653     DoKmsg();
1654 
1655     DumpIpAddrAndRules();
1656 
1657     dump_route_tables();
1658 
1659     RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1660     RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1661     RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
1662 
1663     RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysHigh);
1664 
1665     // The dump mechanism in connectivity is refactored due to modularization work. Connectivity can
1666     // only register with a default priority(NORMAL priority). Dumpstate has to call connectivity
1667     // dump with priority parameters to dump high priority information.
1668     RunDumpsys("SERVICE HIGH connectivity", {"connectivity", "--dump-priority", "HIGH"},
1669                    CommandOptions::WithTimeout(10).Build());
1670 
1671     RunCommand("SYSTEM PROPERTIES", {"getprop"});
1672 
1673     RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
1674 
1675     RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
1676 
1677     /* Binder state is expensive to look at as it uses a lot of memory. */
1678     std::string binder_logs_dir = access("/dev/binderfs/binder_logs", R_OK) ?
1679             "/sys/kernel/debug/binder" : "/dev/binderfs/binder_logs";
1680 
1681     DumpFile("BINDER FAILED TRANSACTION LOG", binder_logs_dir + "/failed_transaction_log");
1682     DumpFile("BINDER TRANSACTION LOG", binder_logs_dir + "/transaction_log");
1683     DumpFile("BINDER TRANSACTIONS", binder_logs_dir + "/transactions");
1684     DumpFile("BINDER STATS", binder_logs_dir + "/stats");
1685     DumpFile("BINDER STATE", binder_logs_dir + "/state");
1686 
1687     /* Add window and surface trace files. */
1688     if (!PropertiesHelper::IsUserBuild()) {
1689         ds.AddDir(WMTRACE_DATA_DIR, false);
1690     }
1691 
1692     ds.AddDir(SNAPSHOTCTL_LOG_DIR, false);
1693 
1694     if (ds.dump_pool_) {
1695         WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_board));
1696     } else {
1697         RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
1698     }
1699 
1700     /* Migrate the ril_dumpstate to a device specific dumpstate? */
1701     int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1702     if (rilDumpstateTimeout > 0) {
1703         // su does not exist on user builds, so try running without it.
1704         // This way any implementations of vril-dump that do not require
1705         // root can run on user builds.
1706         CommandOptions::CommandOptionsBuilder options =
1707             CommandOptions::WithTimeout(rilDumpstateTimeout);
1708         if (!PropertiesHelper::IsUserBuild()) {
1709             options.AsRoot();
1710         }
1711         RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
1712     }
1713 
1714     printf("========================================================\n");
1715     printf("== Android Framework Services\n");
1716     printf("========================================================\n");
1717 
1718     RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal);
1719 
1720     /* Dump Bluetooth HCI logs after getting bluetooth_manager dumpsys */
1721     ds.AddDir("/data/misc/bluetooth/logs", true);
1722 
1723     if (ds.dump_pool_) {
1724         WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_checkins));
1725     } else {
1726         RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_CHECKINS_TASK, DumpCheckins);
1727     }
1728 
1729     RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpAppInfos);
1730 
1731     printf("========================================================\n");
1732     printf("== Dropbox crashes\n");
1733     printf("========================================================\n");
1734 
1735     RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1736     RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1737 
1738     printf("========================================================\n");
1739     printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1740            ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1741     printf("========================================================\n");
1742     printf("== dumpstate: done (id %d)\n", ds.id_);
1743     printf("========================================================\n");
1744 
1745     printf("========================================================\n");
1746     printf("== Obtaining statsd metadata\n");
1747     printf("========================================================\n");
1748     // This differs from the usual dumpsys stats, which is the stats report data.
1749     RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
1750 
1751     // Add linker configuration directory
1752     ds.AddDir(LINKERCONFIG_DIR, true);
1753 
1754     /* Dump frozen cgroupfs */
1755     dump_frozen_cgroupfs();
1756 
1757     if (ds.dump_pool_) {
1758         WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_incident_report));
1759     } else {
1760         RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_INCIDENT_REPORT_TASK,
1761                 DumpIncidentReport);
1762     }
1763 
1764     return Dumpstate::RunStatus::OK;
1765 }
1766 
1767 /*
1768  * Dumps state for the default case; drops root after it's no longer necessary.
1769  *
1770  * Returns RunStatus::OK if everything went fine.
1771  * Returns RunStatus::ERROR if there was an error.
1772  * Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport
1773  * with the caller.
1774  */
DumpstateDefaultAfterCritical()1775 Dumpstate::RunStatus Dumpstate::DumpstateDefaultAfterCritical() {
1776     // Capture first logcat early on; useful to take a snapshot before dumpstate logs take over the
1777     // buffer.
1778     DoLogcat();
1779     // Capture timestamp after first logcat to use in next logcat
1780     time_t logcat_ts = time(nullptr);
1781 
1782     /* collect stack traces from Dalvik and native processes (needs root) */
1783     std::future<std::string> dump_traces;
1784     if (dump_pool_) {
1785         RETURN_IF_USER_DENIED_CONSENT();
1786         // One thread is enough since we only need to enqueue DumpTraces here.
1787         dump_pool_->start(/* thread_counts = */1);
1788 
1789         // DumpTraces takes long time, post it to the another thread in the
1790         // pool, if pool is available
1791         dump_traces = dump_pool_->enqueueTask(
1792             DUMP_TRACES_TASK, &Dumpstate::DumpTraces, &ds, &dump_traces_path);
1793     } else {
1794         RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_TRACES_TASK, ds.DumpTraces,
1795                 &dump_traces_path);
1796     }
1797 
1798     /* Run some operations that require root. */
1799     if (!PropertiesHelper::IsDryRun()) {
1800         ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX);
1801         ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX);
1802     }
1803 
1804     ds.AddDir(RECOVERY_DIR, true);
1805     ds.AddDir(RECOVERY_DATA_DIR, true);
1806     ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
1807     ds.AddDir(LOGPERSIST_DATA_DIR, false);
1808     if (!PropertiesHelper::IsUserBuild()) {
1809         ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1810         ds.AddDir(PROFILE_DATA_DIR_REF, true);
1811         ds.AddZipEntry(ZIP_ROOT_DIR + PACKAGE_DEX_USE_LIST, PACKAGE_DEX_USE_LIST);
1812     }
1813     ds.AddDir(PREREBOOT_DATA_DIR, false);
1814     add_mountinfo();
1815     DumpIpTablesAsRoot();
1816     DumpDynamicPartitionInfo();
1817     ds.AddDir(OTA_METADATA_DIR, true);
1818 
1819     // Capture any IPSec policies in play. No keys are exposed here.
1820     RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1821 
1822     // Dump IPsec stats. No keys are exposed here.
1823     DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
1824 
1825     // Run ss as root so we can see socket marks.
1826     RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1827 
1828     // Run iotop as root to show top 100 IO threads
1829     RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1830 
1831     // Gather shared memory buffer info if the product implements it
1832     RunCommand("Dmabuf dump", {"dmabuf_dump"});
1833     RunCommand("Dmabuf per-buffer/per-exporter/per-device stats", {"dmabuf_dump", "-b"});
1834 
1835     DumpFile("PSI cpu", "/proc/pressure/cpu");
1836     DumpFile("PSI memory", "/proc/pressure/memory");
1837     DumpFile("PSI io", "/proc/pressure/io");
1838 
1839     if (dump_pool_) {
1840         RETURN_IF_USER_DENIED_CONSENT();
1841         WaitForTask(std::move(dump_traces));
1842 
1843         // Current running thread in the pool is the root user also. Delete
1844         // the pool and make a new one later to ensure none of threads in the pool are root.
1845         dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
1846     }
1847     if (!DropRootUser()) {
1848         return Dumpstate::RunStatus::ERROR;
1849     }
1850 
1851     RETURN_IF_USER_DENIED_CONSENT();
1852     Dumpstate::RunStatus status = dumpstate();
1853     // Capture logcat since the last time we did it.
1854     DoSystemLogcat(logcat_ts);
1855     return status;
1856 }
1857 
1858 // Common states for telephony and wifi which are needed to be collected before
1859 // dumpstate drop the root user.
DumpstateRadioAsRoot()1860 static void DumpstateRadioAsRoot() {
1861     DumpIpTablesAsRoot();
1862     ds.AddDir(LOGPERSIST_DATA_DIR, false);
1863 }
1864 
1865 // This method collects common dumpsys for telephony and wifi. Typically, wifi
1866 // reports are fine to include all information, but telephony reports on user
1867 // builds need to strip some content (see DumpstateTelephonyOnly).
DumpstateRadioCommon(bool include_sensitive_info=true)1868 static void DumpstateRadioCommon(bool include_sensitive_info = true) {
1869     // We need to be picky about some stuff for telephony reports on user builds.
1870     if (!include_sensitive_info) {
1871         // Only dump the radio log buffer (other buffers and dumps contain too much unrelated info).
1872         DoRadioLogcat();
1873     } else {
1874         // DumpHals takes long time, post it to the another thread in the pool,
1875         // if pool is available.
1876         std::future<std::string> dump_hals;
1877         if (ds.dump_pool_) {
1878             dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
1879         }
1880         // Contains various system properties and process startup info.
1881         do_dmesg();
1882         // Logs other than the radio buffer may contain package/component names and potential PII.
1883         DoLogcat();
1884         // Too broad for connectivity problems.
1885         DoKmsg();
1886         // DumpHals contains unrelated hardware info (camera, NFC, biometrics, ...).
1887         if (ds.dump_pool_) {
1888             WaitForTask(std::move(dump_hals));
1889         } else {
1890             RUN_SLOW_FUNCTION_AND_LOG(DUMP_HALS_TASK, DumpHals);
1891         }
1892     }
1893 
1894     DumpPacketStats();
1895     DumpIpAddrAndRules();
1896     dump_route_tables();
1897     RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
1898                CommandOptions::WithTimeout(10).Build());
1899 }
1900 
1901 // We use "telephony" here for legacy reasons, though this now really means "connectivity" (cellular
1902 // + wifi + networking). This method collects dumpsys for connectivity debugging only. General rules
1903 // for what can be included on user builds: all reported information MUST directly relate to
1904 // connectivity debugging or customer support and MUST NOT contain unrelated personally identifiable
1905 // information. This information MUST NOT identify user-installed packages (UIDs are OK, package
1906 // names are not), and MUST NOT contain logs of user application traffic.
1907 // TODO(b/148168577) rename this and other related fields/methods to "connectivity" instead.
DumpstateTelephonyOnly(const std::string & calling_package)1908 static void DumpstateTelephonyOnly(const std::string& calling_package) {
1909     DurationReporter duration_reporter("DUMPSTATE");
1910 
1911     const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1912 
1913     const bool include_sensitive_info = !PropertiesHelper::IsUserBuild();
1914 
1915     DumpstateRadioAsRoot();
1916     if (!DropRootUser()) {
1917         return;
1918     }
1919 
1920     // Starts thread pool after the root user is dropped, and two additional threads
1921     // are created for DumpHals in the DumpstateRadioCommon and DumpstateBoard.
1922     std::future<std::string> dump_board;
1923     if (ds.dump_pool_) {
1924         ds.dump_pool_->start(/*thread_counts =*/2);
1925 
1926         // DumpstateBoard takes long time, post it to the another thread in the pool,
1927         // if pool is available.
1928         dump_board = ds.dump_pool_->enqueueTaskWithFd(
1929             DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
1930     }
1931 
1932     DumpstateRadioCommon(include_sensitive_info);
1933 
1934     if (include_sensitive_info) {
1935         // Contains too much unrelated PII, and given the unstructured nature of sysprops, we can't
1936         // really cherrypick all of the connectivity-related ones. Apps generally have no business
1937         // reading these anyway, and there should be APIs to supply the info in a more app-friendly
1938         // way.
1939         RunCommand("SYSTEM PROPERTIES", {"getprop"});
1940     }
1941 
1942     printf("========================================================\n");
1943     printf("== Android Framework Services\n");
1944     printf("========================================================\n");
1945 
1946     RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1947                SEC_TO_MSEC(10));
1948     RunDumpsys("DUMPSYS", {"vcn_management"}, CommandOptions::WithTimeout(90).Build(),
1949                SEC_TO_MSEC(10));
1950     if (include_sensitive_info) {
1951         // Carrier apps' services will be dumped below in dumpsys activity service all-non-platform.
1952         RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
1953                    SEC_TO_MSEC(10));
1954     } else {
1955         // If the caller is a carrier app and has a carrier service, dump it here since we aren't
1956         // running dumpsys activity service all-non-platform below. Due to the increased output, we
1957         // give a higher timeout as well.
1958         RunDumpsys("DUMPSYS", {"carrier_config", "--requesting-package", calling_package},
1959                    CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(30));
1960     }
1961     RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
1962     RunDumpsys("DUMPSYS", {"netpolicy"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
1963     RunDumpsys("DUMPSYS", {"network_management"}, CommandOptions::WithTimeout(90).Build(),
1964                SEC_TO_MSEC(10));
1965     RunDumpsys("DUMPSYS", {"telephony.registry"}, CommandOptions::WithTimeout(90).Build(),
1966                SEC_TO_MSEC(10));
1967     if (include_sensitive_info) {
1968         // Contains raw IP addresses, omit from reports on user builds.
1969         RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
1970         // Contains raw destination IP/MAC addresses, omit from reports on user builds.
1971         RunDumpsys("DUMPSYS", {"connmetrics"}, CommandOptions::WithTimeout(90).Build(),
1972                    SEC_TO_MSEC(10));
1973         // Contains package/component names, omit from reports on user builds.
1974         RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
1975                    SEC_TO_MSEC(10));
1976         // Contains package names, but should be relatively simple to remove them (also contains
1977         // UIDs already), omit from reports on user builds.
1978         RunDumpsys("BATTERYSTATS", {"deviceidle"}, CommandOptions::WithTimeout(90).Build(),
1979                    SEC_TO_MSEC(10));
1980     }
1981 
1982     printf("========================================================\n");
1983     printf("== Running Application Services\n");
1984     printf("========================================================\n");
1985 
1986     RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
1987 
1988     if (include_sensitive_info) {
1989         printf("========================================================\n");
1990         printf("== Running Application Services (non-platform)\n");
1991         printf("========================================================\n");
1992 
1993         // Contains package/component names and potential PII, omit from reports on user builds.
1994         // To get dumps of the active CarrierService(s) on user builds, we supply an argument to the
1995         // carrier_config dumpsys instead.
1996         RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1997                    DUMPSYS_COMPONENTS_OPTIONS);
1998 
1999         printf("========================================================\n");
2000         printf("== Checkins\n");
2001         printf("========================================================\n");
2002 
2003         // Contains package/component names, omit from reports on user builds.
2004         RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
2005     }
2006 
2007     printf("========================================================\n");
2008     printf("== dumpstate: done (id %d)\n", ds.id_);
2009     printf("========================================================\n");
2010 
2011     if (ds.dump_pool_) {
2012         WaitForTask(std::move(dump_board));
2013     } else {
2014         RUN_SLOW_FUNCTION_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
2015     }
2016 }
2017 
2018 // This method collects dumpsys for wifi debugging only
DumpstateWifiOnly()2019 static void DumpstateWifiOnly() {
2020     DurationReporter duration_reporter("DUMPSTATE");
2021 
2022     DumpstateRadioAsRoot();
2023     if (!DropRootUser()) {
2024         return;
2025     }
2026 
2027     // Starts thread pool after the root user is dropped. Only one additional
2028     // thread is needed for DumpHals in the DumpstateRadioCommon.
2029     if (ds.dump_pool_) {
2030         ds.dump_pool_->start(/*thread_counts =*/1);
2031     }
2032 
2033     DumpstateRadioCommon();
2034 
2035     printf("========================================================\n");
2036     printf("== Android Framework Services\n");
2037     printf("========================================================\n");
2038 
2039     RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2040                SEC_TO_MSEC(10));
2041     RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
2042                SEC_TO_MSEC(10));
2043 
2044     printf("========================================================\n");
2045     printf("== dumpstate: done (id %d)\n", ds.id_);
2046     printf("========================================================\n");
2047 }
2048 
DumpTraces(const char ** path)2049 Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
2050     const std::string temp_file_pattern = ds.bugreport_internal_dir_ + "/dumptrace_XXXXXX";
2051     const size_t buf_size = temp_file_pattern.length() + 1;
2052     std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
2053     memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
2054 
2055     // Create a new, empty file to receive all trace dumps.
2056     //
2057     // TODO: This can be simplified once we remove support for the old style
2058     // dumps. We can have a file descriptor passed in to dump_traces instead
2059     // of creating a file, closing it and then reopening it again.
2060     android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
2061     if (fd < 0) {
2062         MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
2063         return RunStatus::OK;
2064     }
2065 
2066     // Nobody should have access to this temporary file except dumpstate, but we
2067     // temporarily grant 'read' to 'others' here because this file is created
2068     // when tombstoned is still running as root, but dumped after dropping. This
2069     // can go away once support for old style dumping has.
2070     const int chmod_ret = fchmod(fd, 0666);
2071     if (chmod_ret < 0) {
2072         MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
2073         return RunStatus::OK;
2074     }
2075 
2076     std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
2077     if (proc.get() == nullptr) {
2078         MYLOGE("opendir /proc failed: %s\n", strerror(errno));
2079         return RunStatus::OK;
2080     }
2081 
2082     // Number of times process dumping has timed out. If we encounter too many
2083     // failures, we'll give up.
2084     int timeout_failures = 0;
2085     bool dalvik_found = false;
2086 
2087     const std::set<int> hal_pids = get_interesting_pids();
2088 
2089     struct dirent* d;
2090     while ((d = readdir(proc.get()))) {
2091         RETURN_IF_USER_DENIED_CONSENT();
2092         int pid = atoi(d->d_name);
2093         if (pid <= 0) {
2094             continue;
2095         }
2096 
2097         const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
2098         std::string exe;
2099         if (!android::base::Readlink(link_name, &exe)) {
2100             continue;
2101         }
2102 
2103         bool is_java_process;
2104         if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
2105             // Don't bother dumping backtraces for the zygote.
2106             if (IsZygote(pid)) {
2107                 continue;
2108             }
2109 
2110             dalvik_found = true;
2111             is_java_process = true;
2112         } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
2113             is_java_process = false;
2114         } else {
2115             // Probably a native process we don't care about, continue.
2116             continue;
2117         }
2118 
2119         // If 3 backtrace dumps fail in a row, consider debuggerd dead.
2120         if (timeout_failures == 3) {
2121             dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
2122             break;
2123         }
2124 
2125         const uint64_t start = Nanotime();
2126         const int ret = dump_backtrace_to_file_timeout(
2127             pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace,
2128             is_java_process ? 5 : 20, fd);
2129 
2130         if (ret == -1) {
2131             // For consistency, the header and footer to this message match those
2132             // dumped by debuggerd in the success case.
2133             dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
2134             dprintf(fd, "Dump failed, likely due to a timeout.\n");
2135             dprintf(fd, "---- end %d ----", pid);
2136             timeout_failures++;
2137             continue;
2138         }
2139 
2140         // We've successfully dumped stack traces, reset the failure count
2141         // and write a summary of the elapsed time to the file and continue with the
2142         // next process.
2143         timeout_failures = 0;
2144 
2145         dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
2146                 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
2147     }
2148 
2149     if (!dalvik_found) {
2150         MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
2151     }
2152 
2153     *path = file_name_buf.release();
2154     return RunStatus::OK;
2155 }
2156 
GetDumpstateHalModeHidl(const Dumpstate::BugreportMode bugreport_mode)2157 static dumpstate_hal_hidl::DumpstateMode GetDumpstateHalModeHidl(
2158     const Dumpstate::BugreportMode bugreport_mode) {
2159     switch (bugreport_mode) {
2160         case Dumpstate::BugreportMode::BUGREPORT_FULL:
2161             return dumpstate_hal_hidl::DumpstateMode::FULL;
2162         case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2163             return dumpstate_hal_hidl::DumpstateMode::INTERACTIVE;
2164         case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2165             return dumpstate_hal_hidl::DumpstateMode::REMOTE;
2166         case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2167             return dumpstate_hal_hidl::DumpstateMode::WEAR;
2168         case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2169             return dumpstate_hal_hidl::DumpstateMode::CONNECTIVITY;
2170         case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2171             return dumpstate_hal_hidl::DumpstateMode::WIFI;
2172         case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2173             return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2174     }
2175     return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2176 }
2177 
GetDumpstateHalModeAidl(const Dumpstate::BugreportMode bugreport_mode)2178 static dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode GetDumpstateHalModeAidl(
2179     const Dumpstate::BugreportMode bugreport_mode) {
2180     switch (bugreport_mode) {
2181         case Dumpstate::BugreportMode::BUGREPORT_FULL:
2182             return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::FULL;
2183         case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2184             return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::INTERACTIVE;
2185         case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2186             return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::REMOTE;
2187         case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2188             return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WEAR;
2189         case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2190             return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::CONNECTIVITY;
2191         case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2192             return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WIFI;
2193         case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2194             return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2195     }
2196     return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2197 }
2198 
DoDumpstateBoardHidl(const sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_1_0,const std::vector<::ndk::ScopedFileDescriptor> & dumpstate_fds,const Dumpstate::BugreportMode bugreport_mode,const size_t timeout_sec)2199 static void DoDumpstateBoardHidl(
2200     const sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_1_0,
2201     const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2202     const Dumpstate::BugreportMode bugreport_mode,
2203     const size_t timeout_sec) {
2204 
2205     using ScopedNativeHandle =
2206         std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
2207     ScopedNativeHandle handle(native_handle_create(static_cast<int>(dumpstate_fds.size()), 0),
2208                               [](native_handle_t* handle) {
2209                                   // we don't close file handle's here
2210                                   // via native_handle_close(handle)
2211                                   // instead we let dumpstate_fds close the file handles when
2212                                   // dumpstate_fds gets destroyed
2213                                   native_handle_delete(handle);
2214                               });
2215     if (handle == nullptr) {
2216         MYLOGE("Could not create native_handle for dumpstate HAL\n");
2217         return;
2218     }
2219 
2220     for (size_t i = 0; i < dumpstate_fds.size(); i++) {
2221         handle.get()->data[i] = dumpstate_fds[i].get();
2222     }
2223 
2224     // Prefer version 1.1 if available. New devices launching with R are no longer allowed to
2225     // implement just 1.0.
2226     const char* descriptor_to_kill;
2227     using DumpstateBoardTask = std::packaged_task<bool()>;
2228     DumpstateBoardTask dumpstate_board_task;
2229     sp<dumpstate_hal_hidl::IDumpstateDevice> dumpstate_hal(
2230         dumpstate_hal_hidl::IDumpstateDevice::castFrom(dumpstate_hal_1_0));
2231     if (dumpstate_hal != nullptr) {
2232         MYLOGI("Using IDumpstateDevice v1.1 HIDL HAL");
2233 
2234         dumpstate_hal_hidl::DumpstateMode dumpstate_hal_mode =
2235             GetDumpstateHalModeHidl(bugreport_mode);
2236 
2237         descriptor_to_kill = dumpstate_hal_hidl::IDumpstateDevice::descriptor;
2238         dumpstate_board_task =
2239             DumpstateBoardTask([timeout_sec, dumpstate_hal_mode, dumpstate_hal, &handle]() -> bool {
2240                 ::android::hardware::Return<dumpstate_hal_hidl::DumpstateStatus> status =
2241                     dumpstate_hal->dumpstateBoard_1_1(handle.get(), dumpstate_hal_mode,
2242                                                       SEC_TO_MSEC(timeout_sec));
2243                 if (!status.isOk()) {
2244                     MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2245                     return false;
2246                 } else if (status != dumpstate_hal_hidl::DumpstateStatus::OK) {
2247                     MYLOGE("dumpstateBoard failed with DumpstateStatus::%s\n",
2248                            dumpstate_hal_hidl::toString(status).c_str());
2249                     return false;
2250                 }
2251                 return true;
2252             });
2253     } else {
2254         MYLOGI("Using IDumpstateDevice v1.0 HIDL HAL");
2255 
2256         descriptor_to_kill = dumpstate_hal_hidl_1_0::IDumpstateDevice::descriptor;
2257         dumpstate_board_task = DumpstateBoardTask([dumpstate_hal_1_0, &handle]() -> bool {
2258             ::android::hardware::Return<void> status =
2259                 dumpstate_hal_1_0->dumpstateBoard(handle.get());
2260             if (!status.isOk()) {
2261                 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2262                 return false;
2263             }
2264             return true;
2265         });
2266     }
2267     auto result = dumpstate_board_task.get_future();
2268     std::thread(std::move(dumpstate_board_task)).detach();
2269 
2270     if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2271         MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2272         if (!android::base::SetProperty(
2273                 "ctl.interface_restart",
2274                 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2275             MYLOGE("Couldn't restart dumpstate HAL\n");
2276         }
2277     }
2278     // Wait some time for init to kill dumpstate vendor HAL
2279     constexpr size_t killing_timeout_sec = 10;
2280     if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2281         MYLOGE(
2282             "killing dumpstateBoard timed out after %zus, continue and "
2283             "there might be racing in content\n",
2284             killing_timeout_sec);
2285     }
2286 }
2287 
DoDumpstateBoardAidl(const std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal,const std::vector<::ndk::ScopedFileDescriptor> & dumpstate_fds,const Dumpstate::BugreportMode bugreport_mode,const size_t timeout_sec)2288 static void DoDumpstateBoardAidl(
2289     const std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal,
2290     const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2291     const Dumpstate::BugreportMode bugreport_mode, const size_t timeout_sec) {
2292     MYLOGI("Using IDumpstateDevice AIDL HAL");
2293 
2294     const char* descriptor_to_kill;
2295     using DumpstateBoardTask = std::packaged_task<bool()>;
2296     DumpstateBoardTask dumpstate_board_task;
2297     dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode dumpstate_hal_mode =
2298         GetDumpstateHalModeAidl(bugreport_mode);
2299 
2300     descriptor_to_kill = dumpstate_hal_aidl::IDumpstateDevice::descriptor;
2301     dumpstate_board_task = DumpstateBoardTask([dumpstate_hal, &dumpstate_fds, dumpstate_hal_mode,
2302                                                timeout_sec]() -> bool {
2303         auto status = dumpstate_hal->dumpstateBoard(dumpstate_fds, dumpstate_hal_mode, timeout_sec);
2304 
2305         if (!status.isOk()) {
2306             MYLOGE("dumpstateBoard failed: %s\n", status.getDescription().c_str());
2307             return false;
2308         }
2309         return true;
2310     });
2311     auto result = dumpstate_board_task.get_future();
2312     std::thread(std::move(dumpstate_board_task)).detach();
2313 
2314     if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2315         MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2316         if (!android::base::SetProperty(
2317                 "ctl.interface_restart",
2318                 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2319             MYLOGE("Couldn't restart dumpstate HAL\n");
2320         }
2321     }
2322     // Wait some time for init to kill dumpstate vendor HAL
2323     constexpr size_t killing_timeout_sec = 10;
2324     if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2325         MYLOGE(
2326             "killing dumpstateBoard timed out after %zus, continue and "
2327             "there might be racing in content\n",
2328             killing_timeout_sec);
2329     }
2330 }
2331 
GetDumpstateBoardAidlService()2332 static std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> GetDumpstateBoardAidlService() {
2333     const std::string aidl_instance_name =
2334         std::string(dumpstate_hal_aidl::IDumpstateDevice::descriptor) + "/default";
2335 
2336     if (!AServiceManager_isDeclared(aidl_instance_name.c_str())) {
2337         return nullptr;
2338     }
2339 
2340     ndk::SpAIBinder dumpstateBinder(AServiceManager_waitForService(aidl_instance_name.c_str()));
2341 
2342     return dumpstate_hal_aidl::IDumpstateDevice::fromBinder(dumpstateBinder);
2343 }
2344 
DumpstateBoard(int out_fd)2345 void Dumpstate::DumpstateBoard(int out_fd) {
2346     dprintf(out_fd, "========================================================\n");
2347     dprintf(out_fd, "== Board\n");
2348     dprintf(out_fd, "========================================================\n");
2349 
2350     /*
2351      * mount debugfs for non-user builds with ro.product.debugfs_restrictions.enabled
2352      * set to true and unmount it after invoking dumpstateBoard_* methods.
2353      * This is to enable debug builds to not have debugfs mounted during runtime.
2354      * It will also ensure that debugfs is only accessed by the dumpstate HAL.
2355      */
2356     auto mount_debugfs =
2357         android::base::GetBoolProperty("ro.product.debugfs_restrictions.enabled", false);
2358     if (mount_debugfs) {
2359         RunCommand("mount debugfs", {"mount", "-t", "debugfs", "debugfs", "/sys/kernel/debug"},
2360                    AS_ROOT_20);
2361         RunCommand("chmod debugfs", {"chmod", "0755", "/sys/kernel/debug"}, AS_ROOT_20);
2362     }
2363 
2364     std::vector<std::string> paths;
2365     std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
2366     for (int i = 0; i < NUM_OF_DUMPS; i++) {
2367         paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
2368                                         kDumpstateBoardFiles[i].c_str()));
2369         remover.emplace_back(android::base::make_scope_guard(
2370             std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
2371     }
2372 
2373     // get dumpstate HAL AIDL implementation
2374     std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal_handle_aidl(
2375         GetDumpstateBoardAidlService());
2376     if (dumpstate_hal_handle_aidl == nullptr) {
2377         MYLOGI("No IDumpstateDevice AIDL implementation\n");
2378     }
2379 
2380     // get dumpstate HAL HIDL implementation, only if AIDL HAL implementation not found
2381     sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_handle_hidl_1_0 = nullptr;
2382     if (dumpstate_hal_handle_aidl == nullptr) {
2383         dumpstate_hal_handle_hidl_1_0 = dumpstate_hal_hidl_1_0::IDumpstateDevice::getService();
2384         if (dumpstate_hal_handle_hidl_1_0 == nullptr) {
2385             MYLOGI("No IDumpstateDevice HIDL implementation\n");
2386         }
2387     }
2388 
2389     // if neither HIDL nor AIDL implementation found, then return
2390     if (dumpstate_hal_handle_hidl_1_0 == nullptr && dumpstate_hal_handle_aidl == nullptr) {
2391         MYLOGE("Could not find IDumpstateDevice implementation\n");
2392         return;
2393     }
2394 
2395     // this is used to hold the file descriptors and when this variable goes out of scope
2396     // the file descriptors are closed
2397     std::vector<::ndk::ScopedFileDescriptor> dumpstate_fds;
2398 
2399     // TODO(128270426): Check for consent in between?
2400     for (size_t i = 0; i < paths.size(); i++) {
2401         MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
2402 
2403         android::base::unique_fd fd(TEMP_FAILURE_RETRY(
2404             open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
2405                  S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
2406         if (fd < 0) {
2407             MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
2408             return;
2409         }
2410 
2411         dumpstate_fds.emplace_back(fd.release());
2412         // we call fd.release() here to make sure "fd" does not get closed
2413         // after "fd" goes out of scope after this block.
2414         // "fd" will be closed when "dumpstate_fds" goes out of scope
2415         // i.e. when we exit this function
2416     }
2417 
2418     // Given that bugreport is required to diagnose failures, it's better to set an arbitrary amount
2419     // of timeout for IDumpstateDevice than to block the rest of bugreport. In the timeout case, we
2420     // will kill the HAL and grab whatever it dumped in time.
2421     constexpr size_t timeout_sec = 45;
2422 
2423     if (dumpstate_hal_handle_aidl != nullptr) {
2424         DoDumpstateBoardAidl(dumpstate_hal_handle_aidl, dumpstate_fds, options_->bugreport_mode,
2425                              timeout_sec);
2426     } else if (dumpstate_hal_handle_hidl_1_0 != nullptr) {
2427         // run HIDL HAL only if AIDL HAL not found
2428         DoDumpstateBoardHidl(dumpstate_hal_handle_hidl_1_0, dumpstate_fds, options_->bugreport_mode,
2429                              timeout_sec);
2430     }
2431 
2432     if (mount_debugfs) {
2433         auto keep_debugfs_mounted =
2434             android::base::GetProperty("persist.dbg.keep_debugfs_mounted", "");
2435         if (keep_debugfs_mounted.empty())
2436             RunCommand("unmount debugfs", {"umount", "/sys/kernel/debug"}, AS_ROOT_20);
2437     }
2438 
2439     auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
2440     for (size_t i = 0; i < paths.size(); i++) {
2441         struct stat s;
2442         if (fstat(dumpstate_fds[i].get(), &s) == -1) {
2443             MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(), strerror(errno));
2444             file_sizes[i] = -1;
2445             continue;
2446         }
2447         file_sizes[i] = s.st_size;
2448     }
2449 
2450     for (size_t i = 0; i < paths.size(); i++) {
2451         if (file_sizes[i] == -1) {
2452             continue;
2453         }
2454         if (file_sizes[i] == 0) {
2455             MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
2456             continue;
2457         }
2458         remover[i].Disable();
2459         EnqueueAddZipEntryAndCleanupIfNeeded(kDumpstateBoardFiles[i], paths[i]);
2460         dprintf(out_fd, "*** See %s entry ***\n", kDumpstateBoardFiles[i].c_str());
2461     }
2462 }
2463 
ShowUsage()2464 static void ShowUsage() {
2465     fprintf(stderr,
2466             "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o directory] [-p] "
2467             "[-s] [-S] [-q] [-P] [-R] [-L] [-V version]\n"
2468             "  -h: display this help message\n"
2469             "  -b: play sound file instead of vibrate, at beginning of job\n"
2470             "  -e: play sound file instead of vibrate, at end of job\n"
2471             "  -o: write to custom directory (only in limited mode)\n"
2472             "  -p: capture screenshot to filename.png\n"
2473             "  -s: write zipped file to control socket (for init)\n"
2474             "  -S: write file location to control socket (for init)\n"
2475             "  -q: disable vibrate\n"
2476             "  -P: send broadcast when started and do progress updates\n"
2477             "  -R: take bugreport in remote mode (shouldn't be used with -P)\n"
2478             "  -w: start binder service and make it wait for a call to startBugreport\n"
2479             "  -L: output limited information that is safe for submission in feedback reports\n"
2480             "  -v: prints the dumpstate header and exit\n");
2481 }
2482 
register_sig_handler()2483 static void register_sig_handler() {
2484     signal(SIGPIPE, SIG_IGN);
2485 }
2486 
FinishZipFile()2487 bool Dumpstate::FinishZipFile() {
2488     // Runs all enqueued adding zip entry and cleanup tasks before finishing the zip file.
2489     if (zip_entry_tasks_) {
2490         zip_entry_tasks_->run(/* do_cancel = */false);
2491     }
2492 
2493     std::string entry_name = base_name_ + "-" + name_ + ".txt";
2494     MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
2495            tmp_path_.c_str());
2496     // Final timestamp
2497     char date[80];
2498     time_t the_real_now_please_stand_up = time(nullptr);
2499     strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
2500     MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
2501            the_real_now_please_stand_up - ds.now_);
2502 
2503     if (!ds.AddZipEntry(entry_name, tmp_path_)) {
2504         MYLOGE("Failed to add text entry to .zip file\n");
2505         return false;
2506     }
2507     if (!AddTextZipEntry("main_entry.txt", entry_name)) {
2508         MYLOGE("Failed to add main_entry.txt to .zip file\n");
2509         return false;
2510     }
2511 
2512     // Add log file (which contains stderr output) to zip...
2513     fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
2514     if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
2515         MYLOGE("Failed to add dumpstate log to .zip file\n");
2516         return false;
2517     }
2518     // TODO: Should truncate the existing file.
2519     // ... and re-open it for further logging.
2520     if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
2521         return false;
2522     }
2523     fprintf(stderr, "\n");
2524 
2525     int32_t err = zip_writer_->Finish();
2526     if (err != 0) {
2527         MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
2528         return false;
2529     }
2530 
2531     // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
2532     ds.zip_file.reset(nullptr);
2533 
2534     MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
2535     android::os::UnlinkAndLogOnError(tmp_path_);
2536 
2537     return true;
2538 }
2539 
SendBroadcast(const std::string & action,const std::vector<std::string> & args)2540 static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) {
2541     // clang-format off
2542     std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0",
2543                     "--receiver-foreground", "--receiver-include-background", "-a", action};
2544     // clang-format on
2545 
2546     am.insert(am.end(), args.begin(), args.end());
2547 
2548     RunCommand("", am,
2549                CommandOptions::WithTimeout(20)
2550                    .Log("Sending broadcast: '%s'\n")
2551                    .Always()
2552                    .DropRoot()
2553                    .RedirectStderr()
2554                    .Build());
2555 }
2556 
Vibrate(int duration_ms)2557 static void Vibrate(int duration_ms) {
2558     // clang-format off
2559     std::vector<std::string> args = {"cmd", "vibrator_manager", "synced", "-f", "-d", "dumpstate",
2560                                      "oneshot", std::to_string(duration_ms)};
2561     RunCommand("", args,
2562                CommandOptions::WithTimeout(10)
2563                    .Log("Vibrate: '%s'\n")
2564                    .Always()
2565                    .Build());
2566     // clang-format on
2567 }
2568 
MaybeResolveSymlink(std::string * path)2569 static void MaybeResolveSymlink(std::string* path) {
2570     std::string resolved_path;
2571     if (android::base::Readlink(*path, &resolved_path)) {
2572         *path = resolved_path;
2573     }
2574 }
2575 
2576 /*
2577  * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
2578  * and adds the version file. Return false if zip_file could not be open to write.
2579  */
PrepareToWriteToFile()2580 static bool PrepareToWriteToFile() {
2581     MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2582 
2583     std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2584     std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
2585     ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
2586     char date[80];
2587     strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2588     ds.name_ = date;
2589 
2590     if (ds.options_->telephony_only) {
2591         ds.base_name_ += "-telephony";
2592     } else if (ds.options_->wifi_only) {
2593         ds.base_name_ += "-wifi";
2594     }
2595 
2596     if (ds.options_->do_screenshot) {
2597         ds.screenshot_path_ = ds.GetPath(ds.CalledByApi() ? "-png.tmp" : ".png");
2598     }
2599     ds.tmp_path_ = ds.GetPath(".tmp");
2600     ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2601 
2602     std::string destination = ds.CalledByApi()
2603                                   ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
2604                                   : ds.bugreport_internal_dir_.c_str();
2605     MYLOGD(
2606         "Bugreport dir: [%s] "
2607         "Base name: [%s] "
2608         "Suffix: [%s] "
2609         "Log path: [%s] "
2610         "Temporary path: [%s] "
2611         "Screenshot path: [%s]\n",
2612         destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2613         ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
2614 
2615     ds.path_ = ds.GetPath(ds.CalledByApi() ? "-zip.tmp" : ".zip");
2616     MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2617     create_parent_dirs(ds.path_.c_str());
2618     ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2619     if (ds.zip_file == nullptr) {
2620         MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2621         return false;
2622     }
2623     ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2624     ds.AddTextZipEntry("version.txt", ds.version_);
2625     return true;
2626 }
2627 
2628 /*
2629  * Finalizes writing to the file by zipping the tmp file to the final location,
2630  * printing zipped file status, etc.
2631  */
FinalizeFile()2632 static void FinalizeFile() {
2633     bool do_text_file = !ds.FinishZipFile();
2634     if (do_text_file) {
2635         MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
2636     }
2637 
2638     std::string final_path = ds.path_;
2639     if (ds.options_->OutputToCustomFile()) {
2640         final_path = ds.GetPath(ds.options_->out_dir, ".zip");
2641         android::os::CopyFileToFile(ds.path_, final_path);
2642     }
2643 
2644     if (ds.options_->stream_to_socket) {
2645         android::os::CopyFileToFd(ds.path_, ds.control_socket_fd_);
2646     } else if (ds.options_->progress_updates_to_socket) {
2647         if (do_text_file) {
2648             dprintf(ds.control_socket_fd_,
2649                     "FAIL:could not create zip file, check %s "
2650                     "for more details\n",
2651                     ds.log_path_.c_str());
2652         } else {
2653             dprintf(ds.control_socket_fd_, "OK:%s\n", final_path.c_str());
2654         }
2655     }
2656 }
2657 
2658 
ModeToString(Dumpstate::BugreportMode mode)2659 static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2660     switch (mode) {
2661         case Dumpstate::BugreportMode::BUGREPORT_FULL:
2662             return "BUGREPORT_FULL";
2663         case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2664             return "BUGREPORT_INTERACTIVE";
2665         case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2666             return "BUGREPORT_REMOTE";
2667         case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2668             return "BUGREPORT_WEAR";
2669         case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2670             return "BUGREPORT_TELEPHONY";
2671         case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2672             return "BUGREPORT_WIFI";
2673         case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2674             return "BUGREPORT_DEFAULT";
2675     }
2676 }
2677 
SetOptionsFromMode(Dumpstate::BugreportMode mode,Dumpstate::DumpOptions * options,bool is_screenshot_requested)2678 static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options,
2679                                bool is_screenshot_requested) {
2680     // Modify com.android.shell.BugreportProgressService#isDefaultScreenshotRequired as well for
2681     // default system screenshots.
2682     options->bugreport_mode = mode;
2683     options->bugreport_mode_string = ModeToString(mode);
2684     switch (mode) {
2685         case Dumpstate::BugreportMode::BUGREPORT_FULL:
2686             options->do_screenshot = is_screenshot_requested;
2687             break;
2688         case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2689             // Currently, the dumpstate binder is only used by Shell to update progress.
2690             options->do_progress_updates = true;
2691             options->do_screenshot = is_screenshot_requested;
2692             break;
2693         case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2694             options->do_vibrate = false;
2695             options->is_remote_mode = true;
2696             options->do_screenshot = false;
2697             break;
2698         case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2699             options->do_progress_updates = true;
2700             options->do_screenshot = is_screenshot_requested;
2701             break;
2702         // TODO(b/148168577) rename TELEPHONY everywhere to CONNECTIVITY.
2703         case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2704             options->telephony_only = true;
2705             options->do_progress_updates = true;
2706             options->do_screenshot = false;
2707             break;
2708         case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2709             options->wifi_only = true;
2710             options->do_screenshot = false;
2711             break;
2712         case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2713             break;
2714     }
2715 }
2716 
LogDumpOptions(const Dumpstate::DumpOptions & options)2717 static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
2718     MYLOGI(
2719         "do_vibrate: %d stream_to_socket: %d progress_updates_to_socket: %d do_screenshot: %d "
2720         "is_remote_mode: %d show_header_only: %d telephony_only: %d "
2721         "wifi_only: %d do_progress_updates: %d fd: %d bugreport_mode: %s "
2722         "limited_only: %d args: %s\n",
2723         options.do_vibrate, options.stream_to_socket, options.progress_updates_to_socket,
2724         options.do_screenshot, options.is_remote_mode, options.show_header_only,
2725         options.telephony_only, options.wifi_only,
2726         options.do_progress_updates, options.bugreport_fd.get(),
2727         options.bugreport_mode_string.c_str(),
2728         options.limited_only, options.args.c_str());
2729 }
2730 
Initialize(BugreportMode bugreport_mode,const android::base::unique_fd & bugreport_fd_in,const android::base::unique_fd & screenshot_fd_in,bool is_screenshot_requested)2731 void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
2732                                         const android::base::unique_fd& bugreport_fd_in,
2733                                         const android::base::unique_fd& screenshot_fd_in,
2734                                         bool is_screenshot_requested) {
2735     // Duplicate the fds because the passed in fds don't outlive the binder transaction.
2736     bugreport_fd.reset(fcntl(bugreport_fd_in.get(), F_DUPFD_CLOEXEC, 0));
2737     screenshot_fd.reset(fcntl(screenshot_fd_in.get(), F_DUPFD_CLOEXEC, 0));
2738 
2739     SetOptionsFromMode(bugreport_mode, this, is_screenshot_requested);
2740 }
2741 
Initialize(int argc,char * argv[])2742 Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
2743     RunStatus status = RunStatus::OK;
2744     int c;
2745     while ((c = getopt(argc, argv, "dho:svqzpLPBRSV:w")) != -1) {
2746         switch (c) {
2747             // clang-format off
2748             case 'o': out_dir = optarg;              break;
2749             case 's': stream_to_socket = true;       break;
2750             case 'S': progress_updates_to_socket = true;    break;
2751             case 'v': show_header_only = true;       break;
2752             case 'q': do_vibrate = false;            break;
2753             case 'p': do_screenshot = true;          break;
2754             case 'P': do_progress_updates = true;    break;
2755             case 'R': is_remote_mode = true;         break;
2756             case 'L': limited_only = true;           break;
2757             case 'V':
2758             case 'd':
2759             case 'z':
2760                 // compatibility no-op
2761                 break;
2762             case 'w':
2763                 // This was already processed
2764                 break;
2765             case 'h':
2766                 status = RunStatus::HELP;
2767                 break;
2768             default:
2769                 fprintf(stderr, "Invalid option: %c\n", c);
2770                 status = RunStatus::INVALID_INPUT;
2771                 break;
2772                 // clang-format on
2773         }
2774     }
2775 
2776     for (int i = 0; i < argc; i++) {
2777         args += argv[i];
2778         if (i < argc - 1) {
2779             args += " ";
2780         }
2781     }
2782 
2783     // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
2784     optind = 1;
2785 
2786     return status;
2787 }
2788 
ValidateOptions() const2789 bool Dumpstate::DumpOptions::ValidateOptions() const {
2790     if (bugreport_fd.get() != -1 && stream_to_socket) {
2791         return false;
2792     }
2793 
2794     if ((progress_updates_to_socket || do_progress_updates) && stream_to_socket) {
2795         return false;
2796     }
2797 
2798     if (is_remote_mode && (do_progress_updates || stream_to_socket)) {
2799         return false;
2800     }
2801     return true;
2802 }
2803 
SetOptions(std::unique_ptr<DumpOptions> options)2804 void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
2805     options_ = std::move(options);
2806 }
2807 
Initialize()2808 void Dumpstate::Initialize() {
2809     /* gets the sequential id */
2810     uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
2811     id_ = ++last_id;
2812     android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
2813 }
2814 
Run(int32_t calling_uid,const std::string & calling_package)2815 Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
2816     Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
2817     if (listener_ != nullptr) {
2818         switch (status) {
2819             case Dumpstate::RunStatus::OK:
2820                 listener_->onFinished();
2821                 break;
2822             case Dumpstate::RunStatus::HELP:
2823                 break;
2824             case Dumpstate::RunStatus::INVALID_INPUT:
2825                 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
2826                 break;
2827             case Dumpstate::RunStatus::ERROR:
2828                 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
2829                 break;
2830             case Dumpstate::RunStatus::USER_CONSENT_DENIED:
2831                 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
2832                 break;
2833             case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
2834                 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
2835                 break;
2836         }
2837     }
2838     return status;
2839 }
2840 
Cancel()2841 void Dumpstate::Cancel() {
2842     CleanupTmpFiles();
2843     android::os::UnlinkAndLogOnError(log_path_);
2844     for (int i = 0; i < NUM_OF_DUMPS; i++) {
2845         android::os::UnlinkAndLogOnError(ds.bugreport_internal_dir_ + "/" +
2846                                          kDumpstateBoardFiles[i]);
2847     }
2848     tombstone_data_.clear();
2849     anr_data_.clear();
2850 
2851     // Instead of shutdown the pool, we delete temporary files directly since
2852     // shutdown blocking the call.
2853     if (dump_pool_) {
2854         dump_pool_->deleteTempFiles();
2855     }
2856     if (zip_entry_tasks_) {
2857         zip_entry_tasks_->run(/*do_cancel =*/ true);
2858     }
2859 }
2860 
2861 /*
2862  * Dumps relevant information to a bugreport based on the given options.
2863  *
2864  * The bugreport can be dumped to a file or streamed to a socket.
2865  *
2866  * How dumping to file works:
2867  * stdout is redirected to a temporary file. This will later become the main bugreport entry.
2868  * stderr is redirected a log file.
2869  *
2870  * The temporary bugreport is then populated via printfs, dumping contents of files and
2871  * output of commands to stdout.
2872  *
2873  * A bunch of other files and dumps are added to the zip archive.
2874  *
2875  * The temporary bugreport file and the log file also get added to the archive.
2876  *
2877  * Bugreports are first generated in a local directory and later copied to the caller's fd
2878  * or directory if supplied.
2879  */
RunInternal(int32_t calling_uid,const std::string & calling_package)2880 Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
2881                                             const std::string& calling_package) {
2882     DurationReporter duration_reporter("RUN INTERNAL", /* logcat_only = */true);
2883     LogDumpOptions(*options_);
2884     if (!options_->ValidateOptions()) {
2885         MYLOGE("Invalid options specified\n");
2886         return RunStatus::INVALID_INPUT;
2887     }
2888     /* set as high priority, and protect from OOM killer */
2889     setpriority(PRIO_PROCESS, 0, -20);
2890 
2891     FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
2892     if (oom_adj) {
2893         fputs("-1000", oom_adj);
2894         fclose(oom_adj);
2895     } else {
2896         /* fallback to kernels <= 2.6.35 */
2897         oom_adj = fopen("/proc/self/oom_adj", "we");
2898         if (oom_adj) {
2899             fputs("-17", oom_adj);
2900             fclose(oom_adj);
2901         }
2902     }
2903 
2904     if (version_ == VERSION_DEFAULT) {
2905         version_ = VERSION_CURRENT;
2906     }
2907 
2908     if (version_ != VERSION_CURRENT) {
2909         MYLOGE("invalid version requested ('%s'); supported values are: ('%s', '%s')\n",
2910                version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str());
2911         return RunStatus::INVALID_INPUT;
2912     }
2913 
2914     if (options_->show_header_only) {
2915         PrintHeader();
2916         return RunStatus::OK;
2917     }
2918 
2919     MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n",
2920             calling_uid, calling_package.c_str());
2921 
2922     // TODO: temporarily set progress until it's part of the Dumpstate constructor
2923     std::string stats_path =
2924         android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str());
2925     progress_.reset(new Progress(stats_path));
2926 
2927     if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
2928         MYLOGE("Failed to acquire wake lock: %s\n", strerror(errno));
2929     } else {
2930         // Wake lock will be released automatically on process death
2931         MYLOGD("Wake lock acquired.\n");
2932     }
2933 
2934     register_sig_handler();
2935 
2936     if (PropertiesHelper::IsDryRun()) {
2937         MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
2938     }
2939 
2940     MYLOGI("dumpstate info: id=%d, args='%s', bugreport_mode= %s bugreport format version: %s\n",
2941            id_, options_->args.c_str(), options_->bugreport_mode_string.c_str(), version_.c_str());
2942 
2943     do_early_screenshot_ = options_->do_progress_updates;
2944 
2945     // If we are going to use a socket, do it as early as possible
2946     // to avoid timeouts from bugreport.
2947     if (options_->stream_to_socket || options_->progress_updates_to_socket) {
2948         MYLOGD("Opening control socket\n");
2949         control_socket_fd_ = open_socket_fn_("dumpstate");
2950         if (control_socket_fd_ == -1) {
2951             return ERROR;
2952         }
2953         if (options_->progress_updates_to_socket) {
2954             options_->do_progress_updates = 1;
2955         }
2956     }
2957 
2958     if (!PrepareToWriteToFile()) {
2959         return ERROR;
2960     }
2961 
2962     // Interactive, wear & telephony modes are default to true.
2963     // and may enable from cli option or when using control socket
2964     if (options_->do_progress_updates) {
2965         // clang-format off
2966         std::vector<std::string> am_args = {
2967                 "--receiver-permission", "android.permission.DUMP",
2968         };
2969         // clang-format on
2970         // Send STARTED broadcast for apps that listen to bugreport generation events
2971         SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
2972         if (options_->progress_updates_to_socket) {
2973             dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
2974         }
2975     }
2976 
2977     /* read /proc/cmdline before dropping root */
2978     FILE *cmdline = fopen("/proc/cmdline", "re");
2979     if (cmdline) {
2980         fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
2981         fclose(cmdline);
2982     }
2983 
2984     if (options_->do_vibrate) {
2985         Vibrate(150);
2986     }
2987 
2988     if (zip_file != nullptr) {
2989         if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
2990             MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
2991                     strerror(errno));
2992         }
2993     }
2994 
2995     int dup_stdout_fd;
2996     int dup_stderr_fd;
2997     // Redirect stderr to log_path_ for debugging.
2998     TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
2999     if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
3000         return ERROR;
3001     }
3002     if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
3003         MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
3004                 strerror(errno));
3005     }
3006 
3007     // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
3008     // moved into zip file later, if zipping.
3009     TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
3010     // TODO: why not write to a file instead of stdout to overcome this problem?
3011     /* TODO: rather than generating a text file now and zipping it later,
3012         it would be more efficient to redirect stdout to the zip entry
3013         directly, but the libziparchive doesn't support that option yet. */
3014     if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
3015         return ERROR;
3016     }
3017     if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
3018         MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
3019                 tmp_path_.c_str(), strerror(errno));
3020     }
3021 
3022     // Don't buffer stdout
3023     setvbuf(stdout, nullptr, _IONBF, 0);
3024 
3025     // Enable the parallel run if the client requests to output to a file.
3026     EnableParallelRunIfNeeded();
3027     // Using scope guard to make sure the dump pool can be shut down correctly.
3028     auto scope_guard_to_shutdown_pool = android::base::make_scope_guard([=]() {
3029         ShutdownDumpPool();
3030     });
3031 
3032     // NOTE: there should be no stdout output until now, otherwise it would break the header.
3033     // In particular, DurationReport objects should be created passing 'title, NULL', so their
3034     // duration is logged into MYLOG instead.
3035     PrintHeader();
3036 
3037     bool is_dumpstate_restricted = options_->telephony_only
3038                                    || options_->wifi_only
3039                                    || options_->limited_only;
3040     if (!is_dumpstate_restricted) {
3041         // Invoke critical dumpsys first to preserve system state, before doing anything else.
3042         RunDumpsysCritical();
3043     }
3044     MaybeTakeEarlyScreenshot();
3045 
3046     if (!is_dumpstate_restricted) {
3047         // Snapshot the system trace now (if running) to avoid that dumpstate's
3048         // own activity pushes out interesting data from the trace ring buffer.
3049         // The trace file is added to the zip by MaybeAddSystemTraceToZip().
3050         MaybeSnapshotSystemTrace();
3051 
3052         // If a winscope trace is running, snapshot it now. It will be pulled into bugreport later
3053         // from WMTRACE_DATA_DIR.
3054         MaybeSnapshotWinTrace();
3055     }
3056     onUiIntensiveBugreportDumpsFinished(calling_uid);
3057     MaybeCheckUserConsent(calling_uid, calling_package);
3058     if (options_->telephony_only) {
3059         DumpstateTelephonyOnly(calling_package);
3060     } else if (options_->wifi_only) {
3061         DumpstateWifiOnly();
3062     } else if (options_->limited_only) {
3063         DumpstateLimitedOnly();
3064     } else {
3065         // Dump state for the default case. This also drops root.
3066         RunStatus s = DumpstateDefaultAfterCritical();
3067         if (s != RunStatus::OK) {
3068             if (s == RunStatus::USER_CONSENT_DENIED) {
3069                 HandleUserConsentDenied();
3070             }
3071             return s;
3072         }
3073     }
3074 
3075     /* close output if needed */
3076     TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
3077 
3078     // Zip the (now complete) .tmp file within the internal directory.
3079     FinalizeFile();
3080 
3081     // Share the final file with the caller if the user has consented or Shell is the caller.
3082     Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
3083     if (CalledByApi()) {
3084         status = CopyBugreportIfUserConsented(calling_uid);
3085         if (status != Dumpstate::RunStatus::OK &&
3086             status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3087             // Do an early return if there were errors. We make an exception for consent
3088             // timing out because it's possible the user got distracted. In this case the
3089             // bugreport is not shared but made available for manual retrieval.
3090             MYLOGI("User denied consent. Returning\n");
3091             return status;
3092         }
3093         if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3094             MYLOGI(
3095                 "Did not receive user consent yet."
3096                 " Will not copy the bugreport artifacts to caller.\n");
3097             const String16 incidentcompanion("incidentcompanion");
3098             sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
3099             if (ics != nullptr) {
3100                 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3101                 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3102                         consent_callback_.get());
3103             } else {
3104                 MYLOGD("Unable to cancel user consent; incidentcompanion service unavailable\n");
3105             }
3106         }
3107     }
3108 
3109     /* vibrate a few but shortly times to let user know it's finished */
3110     if (options_->do_vibrate) {
3111         for (int i = 0; i < 3; i++) {
3112             Vibrate(75);
3113             usleep((75 + 50) * 1000);
3114         }
3115     }
3116 
3117     MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
3118            progress_->GetInitialMax());
3119     progress_->Save();
3120     MYLOGI("done (id %d)\n", id_);
3121 
3122     TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
3123 
3124     if (control_socket_fd_ != -1) {
3125         MYLOGD("Closing control socket\n");
3126         close(control_socket_fd_);
3127     }
3128 
3129     tombstone_data_.clear();
3130     anr_data_.clear();
3131 
3132     return (consent_callback_ != nullptr &&
3133             consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
3134                ? USER_CONSENT_TIMED_OUT
3135                : RunStatus::OK;
3136 }
3137 
MaybeTakeEarlyScreenshot()3138 void Dumpstate::MaybeTakeEarlyScreenshot() {
3139     if (!options_->do_screenshot || !do_early_screenshot_) {
3140         return;
3141     }
3142 
3143     TakeScreenshot();
3144 }
3145 
MaybeSnapshotSystemTrace()3146 void Dumpstate::MaybeSnapshotSystemTrace() {
3147     // If a background system trace is happening and is marked as "suitable for
3148     // bugreport" (i.e. bugreport_score > 0 in the trace config), this command
3149     // will stop it and serialize into SYSTEM_TRACE_SNAPSHOT. In the (likely)
3150     // case that no trace is ongoing, this command is a no-op.
3151     // Note: this should not be enqueued as we need to freeze the trace before
3152     // dumpstate starts. Otherwise the trace ring buffers will contain mostly
3153     // the dumpstate's own activity which is irrelevant.
3154     int res = RunCommand(
3155         "SERIALIZE PERFETTO TRACE",
3156         {"perfetto", "--save-for-bugreport"},
3157         CommandOptions::WithTimeout(10)
3158             .DropRoot()
3159             .CloseAllFileDescriptorsOnExec()
3160             .Build());
3161     has_system_trace_ = res == 0;
3162     // MaybeAddSystemTraceToZip() will take care of copying the trace in the zip
3163     // file in the later stages.
3164 }
3165 
MaybeSnapshotWinTrace()3166 void Dumpstate::MaybeSnapshotWinTrace() {
3167     // Currently WindowManagerService and InputMethodManagerSerivice support WinScope protocol.
3168     for (const auto& service : {"window", "input_method"}) {
3169         RunCommand(
3170             // Empty name because it's not intended to be classified as a bugreport section.
3171             // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
3172             "", {"cmd", service, "tracing", "save-for-bugreport"},
3173             CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
3174     }
3175     // Additionally, include the proto logging from WMShell.
3176     RunCommand(
3177         // Empty name because it's not intended to be classified as a bugreport section.
3178         // Actual logging files can be found as "/data/misc/wmtrace/shell_log.winscope"
3179         // in the bugreport.
3180         "", {"dumpsys", "activity", "service", "SystemUIService",
3181              "WMShell", "protolog", "save-for-bugreport"},
3182         CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
3183 
3184 }
3185 
onUiIntensiveBugreportDumpsFinished(int32_t calling_uid)3186 void Dumpstate::onUiIntensiveBugreportDumpsFinished(int32_t calling_uid) {
3187     if (calling_uid == AID_SHELL || !CalledByApi()) {
3188         return;
3189     }
3190     if (listener_ != nullptr) {
3191         // Let listener know ui intensive bugreport dumps are finished, then it can do event
3192         // handling if required.
3193         listener_->onUiIntensiveBugreportDumpsFinished();
3194     }
3195 }
3196 
MaybeCheckUserConsent(int32_t calling_uid,const std::string & calling_package)3197 void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) {
3198     if (calling_uid == AID_SHELL || !CalledByApi()) {
3199         // No need to get consent for shell triggered dumpstates, or not through
3200         // bugreporting API (i.e. no fd to copy back).
3201         return;
3202     }
3203     consent_callback_ = new ConsentCallback();
3204     const String16 incidentcompanion("incidentcompanion");
3205     sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
3206     android::String16 package(calling_package.c_str());
3207     if (ics != nullptr) {
3208         MYLOGD("Checking user consent via incidentcompanion service\n");
3209         android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
3210             calling_uid, package, String16(), String16(),
3211             0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
3212     } else {
3213         MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
3214     }
3215 }
3216 
IsUserConsentDenied() const3217 bool Dumpstate::IsUserConsentDenied() const {
3218     return ds.consent_callback_ != nullptr &&
3219            ds.consent_callback_->getResult() == UserConsentResult::DENIED;
3220 }
3221 
CalledByApi() const3222 bool Dumpstate::CalledByApi() const {
3223     return ds.options_->bugreport_fd.get() != -1 ? true : false;
3224 }
3225 
CleanupTmpFiles()3226 void Dumpstate::CleanupTmpFiles() {
3227     android::os::UnlinkAndLogOnError(tmp_path_);
3228     android::os::UnlinkAndLogOnError(screenshot_path_);
3229     android::os::UnlinkAndLogOnError(path_);
3230     if (dump_traces_path != nullptr) {
3231         android::os::UnlinkAndLogOnError(dump_traces_path);
3232     }
3233 }
3234 
EnableParallelRunIfNeeded()3235 void Dumpstate::EnableParallelRunIfNeeded() {
3236     if (!PropertiesHelper::IsParallelRun()) {
3237         return;
3238     }
3239     dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
3240     zip_entry_tasks_ = std::make_unique<TaskQueue>();
3241 }
3242 
ShutdownDumpPool()3243 void Dumpstate::ShutdownDumpPool() {
3244     if (dump_pool_) {
3245         dump_pool_.reset();
3246     }
3247     if (zip_entry_tasks_) {
3248         zip_entry_tasks_->run(/* do_cancel = */true);
3249         zip_entry_tasks_ = nullptr;
3250     }
3251 }
3252 
EnqueueAddZipEntryAndCleanupIfNeeded(const std::string & entry_name,const std::string & entry_path)3253 void Dumpstate::EnqueueAddZipEntryAndCleanupIfNeeded(const std::string& entry_name,
3254         const std::string& entry_path) {
3255     auto func_add_zip_entry_and_cleanup = [=](bool task_cancelled) {
3256         if (!task_cancelled) {
3257             AddZipEntry(entry_name, entry_path);
3258         }
3259         android::os::UnlinkAndLogOnError(entry_path);
3260     };
3261     if (zip_entry_tasks_) {
3262         // Enqueues AddZipEntryAndCleanup function if the parallel run is enabled.
3263         zip_entry_tasks_->add(func_add_zip_entry_and_cleanup, _1);
3264     } else {
3265         // Invokes AddZipEntryAndCleanup immediately
3266         std::invoke(func_add_zip_entry_and_cleanup, /* task_cancelled = */false);
3267     }
3268 }
3269 
HandleUserConsentDenied()3270 Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
3271     MYLOGD("User denied consent; deleting files and returning\n");
3272     CleanupTmpFiles();
3273     return USER_CONSENT_DENIED;
3274 }
3275 
CopyBugreportIfUserConsented(int32_t calling_uid)3276 Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented(int32_t calling_uid) {
3277     // If the caller has asked to copy the bugreport over to their directory, we need explicit
3278     // user consent (unless the caller is Shell).
3279     UserConsentResult consent_result;
3280     if (calling_uid == AID_SHELL) {
3281         consent_result = UserConsentResult::APPROVED;
3282     } else {
3283         consent_result = consent_callback_->getResult();
3284     }
3285     if (consent_result == UserConsentResult::UNAVAILABLE) {
3286         // User has not responded yet.
3287         uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
3288         // Telephony is a fast report type, particularly on user builds where information may be
3289         // more aggressively limited. To give the user time to read the consent dialog, increase the
3290         // timeout.
3291         uint64_t timeout_ms = options_->telephony_only ? TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS
3292                                                        : USER_CONSENT_TIMEOUT_MS;
3293         if (elapsed_ms < timeout_ms) {
3294             uint delay_seconds = (timeout_ms - elapsed_ms) / 1000;
3295             MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
3296             sleep(delay_seconds);
3297         }
3298         consent_result = consent_callback_->getResult();
3299     }
3300     if (consent_result == UserConsentResult::DENIED) {
3301         // User has explicitly denied sharing with the app. To be safe delete the
3302         // internal bugreport & tmp files.
3303         return HandleUserConsentDenied();
3304     }
3305     if (consent_result == UserConsentResult::APPROVED) {
3306         bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
3307         if (copy_succeeded) {
3308             android::os::UnlinkAndLogOnError(path_);
3309             if (options_->do_screenshot &&
3310                 options_->screenshot_fd.get() != -1 &&
3311                 !options_->is_screenshot_copied) {
3312                 copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
3313                                                            options_->screenshot_fd.get());
3314                 options_->is_screenshot_copied = copy_succeeded;
3315                 if (copy_succeeded) {
3316                     android::os::UnlinkAndLogOnError(screenshot_path_);
3317                 }
3318             }
3319         }
3320         return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
3321     } else if (consent_result == UserConsentResult::UNAVAILABLE) {
3322         // consent_result is still UNAVAILABLE. The user has likely not responded yet.
3323         // Since we do not have user consent to share the bugreport it does not get
3324         // copied over to the calling app but remains in the internal directory from
3325         // where the user can manually pull it.
3326         std::string final_path = GetPath(".zip");
3327         bool copy_succeeded = android::os::CopyFileToFile(path_, final_path);
3328         if (copy_succeeded) {
3329             android::os::UnlinkAndLogOnError(path_);
3330         }
3331         return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
3332     }
3333     // Unknown result; must be a programming error.
3334     MYLOGE("Unknown user consent result:%d\n", consent_result);
3335     return Dumpstate::RunStatus::ERROR;
3336 }
3337 
ParseCommandlineAndRun(int argc,char * argv[])3338 Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
3339     std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
3340     Dumpstate::RunStatus status = options->Initialize(argc, argv);
3341     if (status == Dumpstate::RunStatus::OK) {
3342         SetOptions(std::move(options));
3343         // When directly running dumpstate binary, the output is not expected to be written
3344         // to any external file descriptor.
3345         assert(options_->bugreport_fd.get() == -1);
3346 
3347         // calling_uid and calling_package are for user consent to share the bugreport with
3348         // an app; they are irrelevant here because bugreport is triggered via command line.
3349         // Update Last ID before calling Run().
3350         Initialize();
3351         status = Run(-1 /* calling_uid */, "" /* calling_package */);
3352     }
3353     return status;
3354 }
3355 
3356 /* Main entry point for dumpstate binary. */
run_main(int argc,char * argv[])3357 int run_main(int argc, char* argv[]) {
3358     Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
3359 
3360     switch (status) {
3361         case Dumpstate::RunStatus::OK:
3362             exit(0);
3363         case Dumpstate::RunStatus::HELP:
3364             ShowUsage();
3365             exit(0);
3366         case Dumpstate::RunStatus::INVALID_INPUT:
3367             fprintf(stderr, "Invalid combination of args\n");
3368             ShowUsage();
3369             exit(1);
3370         case Dumpstate::RunStatus::ERROR:
3371             FALLTHROUGH_INTENDED;
3372         case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3373             FALLTHROUGH_INTENDED;
3374         case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
3375             exit(2);
3376     }
3377 }
3378 
3379 // TODO(111441001): Default DumpOptions to sensible values.
Dumpstate(const std::string & version)3380 Dumpstate::Dumpstate(const std::string& version)
3381     : pid_(getpid()),
3382       options_(new Dumpstate::DumpOptions()),
3383       last_reported_percent_progress_(0),
3384       version_(version),
3385       now_(time(nullptr)),
3386       open_socket_fn_(open_socket) {
3387 }
3388 
GetInstance()3389 Dumpstate& Dumpstate::GetInstance() {
3390     static Dumpstate singleton_(android::base::GetProperty("dumpstate.version", VERSION_CURRENT));
3391     return singleton_;
3392 }
3393 
DurationReporter(const std::string & title,bool logcat_only,bool verbose,int duration_fd)3394 DurationReporter::DurationReporter(const std::string& title, bool logcat_only, bool verbose,
3395         int duration_fd) : title_(title), logcat_only_(logcat_only), verbose_(verbose),
3396         duration_fd_(duration_fd) {
3397     if (!title_.empty()) {
3398         started_ = Nanotime();
3399     }
3400 }
3401 
~DurationReporter()3402 DurationReporter::~DurationReporter() {
3403     if (!title_.empty()) {
3404         float elapsed = (float)(Nanotime() - started_) / NANOS_PER_SEC;
3405         if (elapsed >= .5f || verbose_) {
3406             MYLOGD("Duration of '%s': %.2fs\n", title_.c_str(), elapsed);
3407         }
3408         if (!logcat_only_) {
3409             // Use "Yoda grammar" to make it easier to grep|sort sections.
3410             dprintf(duration_fd_, "------ %.3fs was the duration of '%s' ------\n",
3411                     elapsed, title_.c_str());
3412         }
3413     }
3414 }
3415 
3416 const int32_t Progress::kDefaultMax = 5000;
3417 
Progress(const std::string & path)3418 Progress::Progress(const std::string& path) : Progress(Progress::kDefaultMax, 1.1, path) {
3419 }
3420 
Progress(int32_t initial_max,int32_t progress,float growth_factor)3421 Progress::Progress(int32_t initial_max, int32_t progress, float growth_factor)
3422     : Progress(initial_max, growth_factor, "") {
3423     progress_ = progress;
3424 }
3425 
Progress(int32_t initial_max,float growth_factor,const std::string & path)3426 Progress::Progress(int32_t initial_max, float growth_factor, const std::string& path)
3427     : initial_max_(initial_max),
3428       progress_(0),
3429       max_(initial_max),
3430       growth_factor_(growth_factor),
3431       n_runs_(0),
3432       average_max_(0),
3433       path_(path) {
3434     if (!path_.empty()) {
3435         Load();
3436     }
3437 }
3438 
Load()3439 void Progress::Load() {
3440     MYLOGD("Loading stats from %s\n", path_.c_str());
3441     std::string content;
3442     if (!android::base::ReadFileToString(path_, &content)) {
3443         MYLOGI("Could not read stats from %s; using max of %d\n", path_.c_str(), max_);
3444         return;
3445     }
3446     if (content.empty()) {
3447         MYLOGE("No stats (empty file) on %s; using max of %d\n", path_.c_str(), max_);
3448         return;
3449     }
3450     std::vector<std::string> lines = android::base::Split(content, "\n");
3451 
3452     if (lines.size() < 1) {
3453         MYLOGE("Invalid stats on file %s: not enough lines (%d). Using max of %d\n", path_.c_str(),
3454                (int)lines.size(), max_);
3455         return;
3456     }
3457     char* ptr;
3458     n_runs_ = strtol(lines[0].c_str(), &ptr, 10);
3459     average_max_ = strtol(ptr, nullptr, 10);
3460     if (n_runs_ <= 0 || average_max_ <= 0 || n_runs_ > STATS_MAX_N_RUNS ||
3461         average_max_ > STATS_MAX_AVERAGE) {
3462         MYLOGE("Invalid stats line on file %s: %s\n", path_.c_str(), lines[0].c_str());
3463         initial_max_ = Progress::kDefaultMax;
3464     } else {
3465         initial_max_ = average_max_;
3466     }
3467     max_ = initial_max_;
3468 
3469     MYLOGI("Average max progress: %d in %d runs; estimated max: %d\n", average_max_, n_runs_, max_);
3470 }
3471 
Save()3472 void Progress::Save() {
3473     int32_t total = n_runs_ * average_max_ + progress_;
3474     int32_t runs = n_runs_ + 1;
3475     int32_t average = floor(((float)total) / runs);
3476     MYLOGI("Saving stats (total=%d, runs=%d, average=%d) on %s\n", total, runs, average,
3477            path_.c_str());
3478     if (path_.empty()) {
3479         return;
3480     }
3481 
3482     std::string content = android::base::StringPrintf("%d %d\n", runs, average);
3483     if (!android::base::WriteStringToFile(content, path_)) {
3484         MYLOGE("Could not save stats on %s\n", path_.c_str());
3485     }
3486 }
3487 
Get() const3488 int32_t Progress::Get() const {
3489     return progress_;
3490 }
3491 
Inc(int32_t delta_sec)3492 bool Progress::Inc(int32_t delta_sec) {
3493     bool changed = false;
3494     if (delta_sec >= 0) {
3495         progress_ += delta_sec;
3496         if (progress_ > max_) {
3497             int32_t old_max = max_;
3498             max_ = floor((float)progress_ * growth_factor_);
3499             MYLOGD("Adjusting max progress from %d to %d\n", old_max, max_);
3500             changed = true;
3501         }
3502     }
3503     return changed;
3504 }
3505 
GetMax() const3506 int32_t Progress::GetMax() const {
3507     return max_;
3508 }
3509 
GetInitialMax() const3510 int32_t Progress::GetInitialMax() const {
3511     return initial_max_;
3512 }
3513 
Dump(int fd,const std::string & prefix) const3514 void Progress::Dump(int fd, const std::string& prefix) const {
3515     const char* pr = prefix.c_str();
3516     dprintf(fd, "%sprogress: %d\n", pr, progress_);
3517     dprintf(fd, "%smax: %d\n", pr, max_);
3518     dprintf(fd, "%sinitial_max: %d\n", pr, initial_max_);
3519     dprintf(fd, "%sgrowth_factor: %0.2f\n", pr, growth_factor_);
3520     dprintf(fd, "%spath: %s\n", pr, path_.c_str());
3521     dprintf(fd, "%sn_runs: %d\n", pr, n_runs_);
3522     dprintf(fd, "%saverage_max: %d\n", pr, average_max_);
3523 }
3524 
GetPath(const std::string & suffix) const3525 std::string Dumpstate::GetPath(const std::string& suffix) const {
3526     return GetPath(bugreport_internal_dir_, suffix);
3527 }
3528 
GetPath(const std::string & directory,const std::string & suffix) const3529 std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
3530     return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
3531                                        name_.c_str(), suffix.c_str());
3532 }
3533 
SetProgress(std::unique_ptr<Progress> progress)3534 void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
3535     progress_ = std::move(progress);
3536 }
3537 
for_each_userid(void (* func)(int),const char * header)3538 void for_each_userid(void (*func)(int), const char *header) {
3539     std::string title = header == nullptr ? "for_each_userid" : android::base::StringPrintf(
3540                                                                     "for_each_userid(%s)", header);
3541     DurationReporter duration_reporter(title);
3542     if (PropertiesHelper::IsDryRun()) return;
3543 
3544     DIR *d;
3545     struct dirent *de;
3546 
3547     if (header) printf("\n------ %s ------\n", header);
3548     func(0);
3549 
3550     if (!(d = opendir("/data/system/users"))) {
3551         printf("Failed to open /data/system/users (%s)\n", strerror(errno));
3552         return;
3553     }
3554 
3555     while ((de = readdir(d))) {
3556         int userid;
3557         if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
3558             continue;
3559         }
3560         func(userid);
3561     }
3562 
3563     closedir(d);
3564 }
3565 
__for_each_pid(void (* helper)(int,const char *,void *),const char * header,void * arg)3566 static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
3567     DIR *d;
3568     struct dirent *de;
3569 
3570     if (!(d = opendir("/proc"))) {
3571         printf("Failed to open /proc (%s)\n", strerror(errno));
3572         return;
3573     }
3574 
3575     if (header) printf("\n------ %s ------\n", header);
3576     while ((de = readdir(d))) {
3577         if (ds.IsUserConsentDenied()) {
3578             MYLOGE(
3579                 "Returning early because user denied consent to share bugreport with calling app.");
3580             closedir(d);
3581             return;
3582         }
3583         int pid;
3584         int fd;
3585         char cmdpath[255];
3586         char cmdline[255];
3587 
3588         if (!(pid = atoi(de->d_name))) {
3589             continue;
3590         }
3591 
3592         memset(cmdline, 0, sizeof(cmdline));
3593 
3594         snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
3595         if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3596             TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
3597             close(fd);
3598             if (cmdline[0]) {
3599                 helper(pid, cmdline, arg);
3600                 continue;
3601             }
3602         }
3603 
3604         // if no cmdline, a kernel thread has comm
3605         snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
3606         if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3607             TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
3608             close(fd);
3609             if (cmdline[1]) {
3610                 cmdline[0] = '[';
3611                 size_t len = strcspn(cmdline, "\f\b\r\n");
3612                 cmdline[len] = ']';
3613                 cmdline[len+1] = '\0';
3614             }
3615         }
3616         if (!cmdline[0]) {
3617             strcpy(cmdline, "N/A");
3618         }
3619         helper(pid, cmdline, arg);
3620     }
3621 
3622     closedir(d);
3623 }
3624 
for_each_pid_helper(int pid,const char * cmdline,void * arg)3625 static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
3626     for_each_pid_func *func = (for_each_pid_func*) arg;
3627     func(pid, cmdline);
3628 }
3629 
for_each_pid(for_each_pid_func func,const char * header)3630 void for_each_pid(for_each_pid_func func, const char *header) {
3631     std::string title = header == nullptr ? "for_each_pid"
3632                                           : android::base::StringPrintf("for_each_pid(%s)", header);
3633     DurationReporter duration_reporter(title);
3634     if (PropertiesHelper::IsDryRun()) return;
3635 
3636     __for_each_pid(for_each_pid_helper, header, (void *) func);
3637 }
3638 
for_each_tid_helper(int pid,const char * cmdline,void * arg)3639 static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
3640     DIR *d;
3641     struct dirent *de;
3642     char taskpath[255];
3643     for_each_tid_func *func = (for_each_tid_func *) arg;
3644 
3645     snprintf(taskpath, sizeof(taskpath), "/proc/%d/task", pid);
3646 
3647     if (!(d = opendir(taskpath))) {
3648         printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
3649         return;
3650     }
3651 
3652     func(pid, pid, cmdline);
3653 
3654     while ((de = readdir(d))) {
3655         if (ds.IsUserConsentDenied()) {
3656             MYLOGE(
3657                 "Returning early because user denied consent to share bugreport with calling app.");
3658             closedir(d);
3659             return;
3660         }
3661         int tid;
3662         int fd;
3663         char commpath[255];
3664         char comm[255];
3665 
3666         if (!(tid = atoi(de->d_name))) {
3667             continue;
3668         }
3669 
3670         if (tid == pid)
3671             continue;
3672 
3673         snprintf(commpath, sizeof(commpath), "/proc/%d/comm", tid);
3674         memset(comm, 0, sizeof(comm));
3675         if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
3676             strcpy(comm, "N/A");
3677         } else {
3678             char *c;
3679             TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
3680             close(fd);
3681 
3682             c = strrchr(comm, '\n');
3683             if (c) {
3684                 *c = '\0';
3685             }
3686         }
3687         func(pid, tid, comm);
3688     }
3689 
3690     closedir(d);
3691 }
3692 
for_each_tid(for_each_tid_func func,const char * header)3693 void for_each_tid(for_each_tid_func func, const char *header) {
3694     std::string title = header == nullptr ? "for_each_tid"
3695                                           : android::base::StringPrintf("for_each_tid(%s)", header);
3696     DurationReporter duration_reporter(title);
3697 
3698     if (PropertiesHelper::IsDryRun()) return;
3699 
3700     __for_each_pid(for_each_tid_helper, header, (void *) func);
3701 }
3702 
show_wchan(int pid,int tid,const char * name)3703 void show_wchan(int pid, int tid, const char *name) {
3704     if (PropertiesHelper::IsDryRun()) return;
3705 
3706     char path[255];
3707     char buffer[255];
3708     int fd, ret, save_errno;
3709     char name_buffer[255];
3710 
3711     memset(buffer, 0, sizeof(buffer));
3712 
3713     snprintf(path, sizeof(path), "/proc/%d/wchan", tid);
3714     if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
3715         printf("Failed to open '%s' (%s)\n", path, strerror(errno));
3716         return;
3717     }
3718 
3719     ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3720     save_errno = errno;
3721     close(fd);
3722 
3723     if (ret < 0) {
3724         printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
3725         return;
3726     }
3727 
3728     snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
3729              pid == tid ? 0 : 3, "", name);
3730 
3731     printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
3732 
3733     return;
3734 }
3735 
3736 // print time in centiseconds
snprcent(char * buffer,size_t len,size_t spc,unsigned long long time)3737 static void snprcent(char *buffer, size_t len, size_t spc,
3738                      unsigned long long time) {
3739     static long hz; // cache discovered hz
3740 
3741     if (hz <= 0) {
3742         hz = sysconf(_SC_CLK_TCK);
3743         if (hz <= 0) {
3744             hz = 1000;
3745         }
3746     }
3747 
3748     // convert to centiseconds
3749     time = (time * 100 + (hz / 2)) / hz;
3750 
3751     char str[16];
3752 
3753     snprintf(str, sizeof(str), " %llu.%02u",
3754              time / 100, (unsigned)(time % 100));
3755     size_t offset = strlen(buffer);
3756     snprintf(buffer + offset, (len > offset) ? len - offset : 0,
3757              "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
3758 }
3759 
3760 // print permille as a percent
snprdec(char * buffer,size_t len,size_t spc,unsigned permille)3761 static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
3762     char str[16];
3763 
3764     snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
3765     size_t offset = strlen(buffer);
3766     snprintf(buffer + offset, (len > offset) ? len - offset : 0,
3767              "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
3768 }
3769 
show_showtime(int pid,const char * name)3770 void show_showtime(int pid, const char *name) {
3771     if (PropertiesHelper::IsDryRun()) return;
3772 
3773     char path[255];
3774     char buffer[1023];
3775     int fd, ret, save_errno;
3776 
3777     memset(buffer, 0, sizeof(buffer));
3778 
3779     snprintf(path, sizeof(path), "/proc/%d/stat", pid);
3780     if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
3781         printf("Failed to open '%s' (%s)\n", path, strerror(errno));
3782         return;
3783     }
3784 
3785     ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3786     save_errno = errno;
3787     close(fd);
3788 
3789     if (ret < 0) {
3790         printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
3791         return;
3792     }
3793 
3794     // field 14 is utime
3795     // field 15 is stime
3796     // field 42 is iotime
3797     unsigned long long utime = 0, stime = 0, iotime = 0;
3798     if (sscanf(buffer,
3799                "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
3800                "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
3801                "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
3802                "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
3803                &utime, &stime, &iotime) != 3) {
3804         return;
3805     }
3806 
3807     unsigned long long total = utime + stime;
3808     if (!total) {
3809         return;
3810     }
3811 
3812     unsigned permille = (iotime * 1000 + (total / 2)) / total;
3813     if (permille > 1000) {
3814         permille = 1000;
3815     }
3816 
3817     // try to beautify and stabilize columns at <80 characters
3818     snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
3819     if ((name[0] != '[') || utime) {
3820         snprcent(buffer, sizeof(buffer), 57, utime);
3821     }
3822     snprcent(buffer, sizeof(buffer), 65, stime);
3823     if ((name[0] != '[') || iotime) {
3824         snprcent(buffer, sizeof(buffer), 73, iotime);
3825     }
3826     if (iotime) {
3827         snprdec(buffer, sizeof(buffer), 79, permille);
3828     }
3829     puts(buffer);  // adds a trailing newline
3830 
3831     return;
3832 }
3833 
do_dmesg()3834 void do_dmesg() {
3835     const char *title = "KERNEL LOG (dmesg)";
3836     DurationReporter duration_reporter(title);
3837     printf("------ %s ------\n", title);
3838 
3839     if (PropertiesHelper::IsDryRun()) return;
3840 
3841     /* Get size of kernel buffer */
3842     int size = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
3843     if (size <= 0) {
3844         printf("Unexpected klogctl return value: %d\n\n", size);
3845         return;
3846     }
3847     char *buf = (char *) malloc(size + 1);
3848     if (buf == nullptr) {
3849         printf("memory allocation failed\n\n");
3850         return;
3851     }
3852     int retval = klogctl(KLOG_READ_ALL, buf, size);
3853     if (retval < 0) {
3854         printf("klogctl failure\n\n");
3855         free(buf);
3856         return;
3857     }
3858     buf[retval] = '\0';
3859     printf("%s\n\n", buf);
3860     free(buf);
3861     return;
3862 }
3863 
do_showmap(int pid,const char * name)3864 void do_showmap(int pid, const char *name) {
3865     char title[255];
3866     char arg[255];
3867 
3868     snprintf(title, sizeof(title), "SHOW MAP %d (%s)", pid, name);
3869     snprintf(arg, sizeof(arg), "%d", pid);
3870     RunCommand(title, {"showmap", "-q", arg}, CommandOptions::AS_ROOT);
3871 }
3872 
DumpFile(const std::string & title,const std::string & path)3873 int Dumpstate::DumpFile(const std::string& title, const std::string& path) {
3874     DurationReporter duration_reporter(title);
3875 
3876     int status = DumpFileToFd(STDOUT_FILENO, title, path);
3877 
3878     UpdateProgress(WEIGHT_FILE);
3879 
3880     return status;
3881 }
3882 
read_file_as_long(const char * path,long int * output)3883 int read_file_as_long(const char *path, long int *output) {
3884     int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
3885     if (fd < 0) {
3886         int err = errno;
3887         MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
3888         return -1;
3889     }
3890     char buffer[50];
3891     ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3892     if (bytes_read == -1) {
3893         MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
3894         return -2;
3895     }
3896     if (bytes_read == 0) {
3897         MYLOGE("File %s is empty\n", path);
3898         return -3;
3899     }
3900     *output = atoi(buffer);
3901     return 0;
3902 }
3903 
3904 /* calls skip to gate calling dump_from_fd recursively
3905  * in the specified directory. dump_from_fd defaults to
3906  * dump_file_from_fd above when set to NULL. skip defaults
3907  * to false when set to NULL. dump_from_fd will always be
3908  * called with title NULL.
3909  */
dump_files(const std::string & title,const char * dir,bool (* skip)(const char * path),int (* dump_from_fd)(const char * title,const char * path,int fd))3910 int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
3911                int (*dump_from_fd)(const char* title, const char* path, int fd)) {
3912     DurationReporter duration_reporter(title);
3913     DIR *dirp;
3914     struct dirent *d;
3915     char *newpath = nullptr;
3916     const char *slash = "/";
3917     int retval = 0;
3918 
3919     if (!title.empty()) {
3920         printf("------ %s (%s) ------\n", title.c_str(), dir);
3921     }
3922     if (PropertiesHelper::IsDryRun()) return 0;
3923 
3924     if (dir[strlen(dir) - 1] == '/') {
3925         ++slash;
3926     }
3927     dirp = opendir(dir);
3928     if (dirp == nullptr) {
3929         retval = -errno;
3930         MYLOGE("%s: %s\n", dir, strerror(errno));
3931         return retval;
3932     }
3933 
3934     if (!dump_from_fd) {
3935         dump_from_fd = dump_file_from_fd;
3936     }
3937     for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
3938         if ((d->d_name[0] == '.')
3939          && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
3940           || (d->d_name[1] == '\0'))) {
3941             continue;
3942         }
3943         asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
3944                  (d->d_type == DT_DIR) ? "/" : "");
3945         if (!newpath) {
3946             retval = -errno;
3947             continue;
3948         }
3949         if (skip && (*skip)(newpath)) {
3950             continue;
3951         }
3952         if (d->d_type == DT_DIR) {
3953             int ret = dump_files("", newpath, skip, dump_from_fd);
3954             if (ret < 0) {
3955                 retval = ret;
3956             }
3957             continue;
3958         }
3959         android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
3960         if (fd.get() < 0) {
3961             retval = -1;
3962             printf("*** %s: %s\n", newpath, strerror(errno));
3963             continue;
3964         }
3965         (*dump_from_fd)(nullptr, newpath, fd.get());
3966     }
3967     closedir(dirp);
3968     if (!title.empty()) {
3969         printf("\n");
3970     }
3971     return retval;
3972 }
3973 
3974 /* fd must have been opened with the flag O_NONBLOCK. With this flag set,
3975  * it's possible to avoid issues where opening the file itself can get
3976  * stuck.
3977  */
dump_file_from_fd(const char * title,const char * path,int fd)3978 int dump_file_from_fd(const char *title, const char *path, int fd) {
3979     if (PropertiesHelper::IsDryRun()) return 0;
3980 
3981     int flags = fcntl(fd, F_GETFL);
3982     if (flags == -1) {
3983         printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
3984         return -1;
3985     } else if (!(flags & O_NONBLOCK)) {
3986         printf("*** %s: fd must have O_NONBLOCK set.\n", path);
3987         return -1;
3988     }
3989     return DumpFileFromFdToFd(title, path, fd, STDOUT_FILENO, PropertiesHelper::IsDryRun());
3990 }
3991 
RunCommand(const std::string & title,const std::vector<std::string> & full_command,const CommandOptions & options,bool verbose_duration,int out_fd)3992 int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& full_command,
3993                           const CommandOptions& options, bool verbose_duration, int out_fd) {
3994     DurationReporter duration_reporter(title, false /* logcat_only */,
3995                                        verbose_duration, out_fd);
3996 
3997     int status = RunCommandToFd(out_fd, title, full_command, options);
3998 
3999     /* TODO: for now we're simplifying the progress calculation by using the
4000      * timeout as the weight. It's a good approximation for most cases, except when calling dumpsys,
4001      * where its weight should be much higher proportionally to its timeout.
4002      * Ideally, it should use a options.EstimatedDuration() instead...*/
4003     UpdateProgress(options.Timeout());
4004 
4005     return status;
4006 }
4007 
RunDumpsys(const std::string & title,const std::vector<std::string> & dumpsys_args,const CommandOptions & options,long dumpsysTimeoutMs,int out_fd)4008 void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
4009                            const CommandOptions& options, long dumpsysTimeoutMs, int out_fd) {
4010     long timeout_ms = dumpsysTimeoutMs > 0 ? dumpsysTimeoutMs : options.TimeoutInMs();
4011     std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-T", std::to_string(timeout_ms)};
4012     dumpsys.insert(dumpsys.end(), dumpsys_args.begin(), dumpsys_args.end());
4013     RunCommand(title, dumpsys, options, false, out_fd);
4014 }
4015 
open_socket(const char * service)4016 static int open_socket(const char* service) {
4017     int s = android_get_control_socket(service);
4018     if (s < 0) {
4019         MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
4020         return -1;
4021     }
4022     fcntl(s, F_SETFD, FD_CLOEXEC);
4023 
4024     // Set backlog to 0 to make sure that queue size will be minimum.
4025     // In Linux, because the minimum queue will be 1, connect() will be blocked
4026     // if the other clients already called connect() and the connection request was not accepted.
4027     if (listen(s, 0) < 0) {
4028         MYLOGE("listen(control socket): %s\n", strerror(errno));
4029         return -1;
4030     }
4031 
4032     struct sockaddr addr;
4033     socklen_t alen = sizeof(addr);
4034     int fd = accept4(s, &addr, &alen, SOCK_CLOEXEC);
4035 
4036     // Close socket just after accept(), to make sure that connect() by client will get error
4037     // when the socket is used by the other services.
4038     // There is still a race condition possibility between accept and close, but there is no way
4039     // to close-on-accept atomically.
4040     // See detail; b/123306389#comment25
4041     close(s);
4042 
4043     if (fd < 0) {
4044         MYLOGE("accept(control socket): %s\n", strerror(errno));
4045         return -1;
4046     }
4047 
4048     return fd;
4049 }
4050 
4051 // TODO: should call is_valid_output_file and/or be merged into it.
create_parent_dirs(const char * path)4052 void create_parent_dirs(const char *path) {
4053     char *chp = const_cast<char *> (path);
4054 
4055     /* skip initial slash */
4056     if (chp[0] == '/')
4057         chp++;
4058 
4059     /* create leading directories, if necessary */
4060     struct stat dir_stat;
4061     while (chp && chp[0]) {
4062         chp = strchr(chp, '/');
4063         if (chp) {
4064             *chp = 0;
4065             if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
4066                 MYLOGI("Creating directory %s\n", path);
4067                 if (mkdir(path, 0770)) { /* drwxrwx--- */
4068                     MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
4069                 } else if (chown(path, AID_SHELL, AID_SHELL)) {
4070                     MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
4071                 }
4072             }
4073             *chp++ = '/';
4074         }
4075     }
4076 }
4077 
_redirect_to_file(FILE * redirect,char * path,int truncate_flag)4078 bool _redirect_to_file(FILE* redirect, char* path, int truncate_flag) {
4079     create_parent_dirs(path);
4080 
4081     int fd = TEMP_FAILURE_RETRY(open(path,
4082                                      O_WRONLY | O_CREAT | truncate_flag | O_CLOEXEC | O_NOFOLLOW,
4083                                      S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
4084     if (fd < 0) {
4085         MYLOGE("%s: %s\n", path, strerror(errno));
4086         return false;
4087     }
4088 
4089     TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
4090     close(fd);
4091     return true;
4092 }
4093 
redirect_to_file(FILE * redirect,char * path)4094 bool redirect_to_file(FILE* redirect, char* path) {
4095     return _redirect_to_file(redirect, path, O_TRUNC);
4096 }
4097 
redirect_to_existing_file(FILE * redirect,char * path)4098 bool redirect_to_existing_file(FILE* redirect, char* path) {
4099     return _redirect_to_file(redirect, path, O_APPEND);
4100 }
4101 
dump_route_tables()4102 void dump_route_tables() {
4103     DurationReporter duration_reporter("DUMP ROUTE TABLES");
4104     if (PropertiesHelper::IsDryRun()) return;
4105     const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
4106     ds.DumpFile("RT_TABLES", RT_TABLES_PATH);
4107     FILE* fp = fopen(RT_TABLES_PATH, "re");
4108     if (!fp) {
4109         printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
4110         return;
4111     }
4112     char table[16];
4113     // Each line has an integer (the table number), a space, and a string (the table name). We only
4114     // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
4115     // Add a fixed max limit so this doesn't go awry.
4116     for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
4117         RunCommand("ROUTE TABLE IPv4", {"ip", "-4", "route", "show", "table", table});
4118         RunCommand("ROUTE TABLE IPv6", {"ip", "-6", "route", "show", "table", table});
4119     }
4120     fclose(fp);
4121 }
4122 
dump_frozen_cgroupfs(const char * dir,int level,int (* dump_from_fd)(const char * title,const char * path,int fd))4123 void dump_frozen_cgroupfs(const char *dir, int level,
4124         int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4125     DIR *dirp;
4126     struct dirent *d;
4127     char *newpath = nullptr;
4128 
4129     dirp = opendir(dir);
4130     if (dirp == nullptr) {
4131         MYLOGE("%s: %s\n", dir, strerror(errno));
4132         return;
4133     }
4134 
4135     for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4136         if ((d->d_name[0] == '.')
4137          && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4138           || (d->d_name[1] == '\0'))) {
4139             continue;
4140         }
4141         if (d->d_type == DT_DIR) {
4142             asprintf(&newpath, "%s/%s/", dir, d->d_name);
4143             if (!newpath) {
4144                 continue;
4145             }
4146             if (level == 0 && !strncmp(d->d_name, "uid_", 4)) {
4147                 dump_frozen_cgroupfs(newpath, 1, dump_from_fd);
4148             } else if (level == 1 && !strncmp(d->d_name, "pid_", 4)) {
4149                 char *freezer = nullptr;
4150                 asprintf(&freezer, "%s/%s", newpath, "cgroup.freeze");
4151                 if (freezer) {
4152                     FILE* fp = fopen(freezer, "r");
4153                     if (fp != NULL) {
4154                         int frozen;
4155                         fscanf(fp, "%d", &frozen);
4156                         if (frozen > 0) {
4157                             dump_files("", newpath, skip_none, dump_from_fd);
4158                         }
4159                         fclose(fp);
4160                     }
4161                     free(freezer);
4162                 }
4163             }
4164         }
4165     }
4166     closedir(dirp);
4167 }
4168 
dump_frozen_cgroupfs()4169 void dump_frozen_cgroupfs() {
4170     MYLOGD("Adding frozen processes from %s\n", CGROUPFS_DIR);
4171     DurationReporter duration_reporter("FROZEN CGROUPFS");
4172     if (PropertiesHelper::IsDryRun()) return;
4173     dump_frozen_cgroupfs(CGROUPFS_DIR, 0, _add_file_from_fd);
4174 }
4175 
UpdateProgress(int32_t delta_sec)4176 void Dumpstate::UpdateProgress(int32_t delta_sec) {
4177     if (progress_ == nullptr) {
4178         MYLOGE("UpdateProgress: progress_ not set\n");
4179         return;
4180     }
4181     // This function updates progress related members of the dumpstate and reports
4182     // progress percentage to the bugreport client. Since it could be called by
4183     // different dump tasks at the same time if the parallel run is enabled, a
4184     // mutex lock is necessary here to synchronize the call.
4185     std::lock_guard<std::recursive_mutex> lock(mutex_);
4186 
4187     // Always update progess so stats can be tuned...
4188     progress_->Inc(delta_sec);
4189 
4190     // ...but only notifiy listeners when necessary.
4191     if (!options_->do_progress_updates) return;
4192 
4193     int progress = progress_->Get();
4194     int max = progress_->GetMax();
4195     int percent = 100 * progress / max;
4196 
4197     if (last_reported_percent_progress_ > 0 && percent <= last_reported_percent_progress_) {
4198         return;
4199     }
4200     last_reported_percent_progress_ = percent;
4201 
4202     if (control_socket_fd_ >= 0) {
4203         dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
4204         fsync(control_socket_fd_);
4205     }
4206 
4207     if (listener_ != nullptr) {
4208         if (percent % 10 == 0) {
4209             // We don't want to spam logcat, so only log multiples of 10.
4210             MYLOGD("Setting progress: %d/%d (%d%%)\n", progress, max, percent);
4211         } else {
4212             // stderr is ignored on normal invocations, but useful when calling
4213             // /system/bin/dumpstate directly for debuggging.
4214             fprintf(stderr, "Setting progress: %d/%d (%d%%)\n", progress, max, percent);
4215         }
4216 
4217         listener_->onProgress(percent);
4218     }
4219 }
4220 
TakeScreenshot(const std::string & path)4221 void Dumpstate::TakeScreenshot(const std::string& path) {
4222     const std::string& real_path = path.empty() ? screenshot_path_ : path;
4223     int status =
4224         RunCommand("", {"/system/bin/screencap", "-p", real_path},
4225                    CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
4226     if (status == 0) {
4227         MYLOGD("Screenshot saved on %s\n", real_path.c_str());
4228     } else {
4229         MYLOGE("Failed to take screenshot on %s\n", real_path.c_str());
4230     }
4231     if (listener_ != nullptr) {
4232         // Show a visual indication to indicate screenshot is taken via
4233         // IDumpstateListener.onScreenshotTaken()
4234         listener_->onScreenshotTaken(status == 0);
4235     }
4236 }
4237 
is_dir(const char * pathname)4238 bool is_dir(const char* pathname) {
4239     struct stat info;
4240     if (stat(pathname, &info) == -1) {
4241         return false;
4242     }
4243     return S_ISDIR(info.st_mode);
4244 }
4245 
get_mtime(int fd,time_t default_mtime)4246 time_t get_mtime(int fd, time_t default_mtime) {
4247     struct stat info;
4248     if (fstat(fd, &info) == -1) {
4249         return default_mtime;
4250     }
4251     return info.st_mtime;
4252 }
4253