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