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