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