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