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