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