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