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