blob: 376d57a624e0697a3e34839c17fc07d7a6252ed8 [file] [log] [blame]
Colin Crossf45fa6b2012-03-26 12:38:26 -07001/*
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 */
Felipe Lemef0292972016-11-22 13:57:05 -080016
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070017#define LOG_TAG "dumpstate"
Kevin Jeon2c02e8e2022-07-07 21:45:17 +000018#define ATRACE_TAG ATRACE_TAG_ALWAYS
Colin Crossf45fa6b2012-03-26 12:38:26 -070019
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -070020#include <dirent.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070021#include <errno.h>
22#include <fcntl.h>
Nikita Ioffea325a572019-05-16 19:49:47 +010023#include <inttypes.h>
Felipe Lemead5f6c42015-11-30 14:26:46 -080024#include <libgen.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070025#include <limits.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010026#include <math.h>
27#include <poll.h>
Mark Salyzyn8f37aa52015-06-12 12:28:24 -070028#include <stdbool.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070029#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -070032#include <sys/mount.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080033#include <sys/poll.h>
Christopher Ferris7dc7f322014-07-22 16:08:19 -070034#include <sys/prctl.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070035#include <sys/resource.h>
36#include <sys/stat.h>
37#include <sys/time.h>
38#include <sys/wait.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010039#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>
Colin Crossf45fa6b2012-03-26 12:38:26 -070046#include <unistd.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070047
48#include <chrono>
Hridya Valsarajuac582cd2019-08-05 15:39:54 -070049#include <cmath>
Abhijeet Kaurd3cca0d2019-03-25 12:04:16 +000050#include <fstream>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070051#include <functional>
52#include <future>
Narayan Kamath8f788292017-05-25 13:20:39 +010053#include <memory>
Hridya Valsarajuac582cd2019-08-05 15:39:54 -070054#include <numeric>
Narayan Kamath8f788292017-05-25 13:20:39 +010055#include <regex>
56#include <set>
57#include <string>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070058#include <utility>
Narayan Kamath8f788292017-05-25 13:20:39 +010059#include <vector>
Colin Crossf45fa6b2012-03-26 12:38:26 -070060
Kedar Chitnis9fd8c052021-11-16 09:09:22 +000061#include <aidl/android/hardware/dumpstate/IDumpstateDevice.h>
Felipe Leme96c2bbb2016-09-26 09:21:21 -070062#include <android-base/file.h>
63#include <android-base/properties.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070064#include <android-base/scopeguard.h>
Elliott Hughes9dc117c2015-12-07 14:21:50 -080065#include <android-base/stringprintf.h>
Naveen Kalla058e1e82016-10-19 21:38:44 -070066#include <android-base/strings.h>
Andreas Gampeaff68432016-07-18 18:01:27 -070067#include <android-base/unique_fd.h>
Kedar Chitnis9fd8c052021-11-16 09:09:22 +000068#include <android/binder_manager.h>
69#include <android/binder_process.h>
Nikita Ioffea325a572019-05-16 19:49:47 +010070#include <android/content/pm/IPackageManagerNative.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080071#include <android/hardware/dumpstate/1.0/IDumpstateDevice.h>
Hunter Knepshield8540faf2020-02-04 19:47:20 -080072#include <android/hardware/dumpstate/1.1/IDumpstateDevice.h>
73#include <android/hardware/dumpstate/1.1/types.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080074#include <android/hidl/manager/1.0/IServiceManager.h>
Nandana Duttd2f5f082019-01-18 17:13:52 +000075#include <android/os/IIncidentCompanion.h>
Nikita Ioffea325a572019-05-16 19:49:47 +010076#include <binder/IServiceManager.h>
Nikhil Kumar28ce35e2023-01-10 14:32:44 +000077#include <cutils/multiuser.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080078#include <cutils/native_handle.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070079#include <cutils/properties.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010080#include <cutils/sockets.h>
Kevin Jeon2c02e8e2022-07-07 21:45:17 +000081#include <cutils/trace.h>
Nandana Duttfaafd522019-03-11 09:23:09 +000082#include <debuggerd/client.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080083#include <dumpsys.h>
Nandana Duttfaafd522019-03-11 09:23:09 +000084#include <dumputils/dump_utils.h>
Sahana Raof35ed432019-07-12 10:47:52 +010085#include <hardware_legacy/power.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080086#include <hidl/ServiceManagement.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010087#include <log/log.h>
Tom Cherryf4472f32020-08-05 09:31:17 -070088#include <log/log_read.h>
Felipe Leme75876a22016-10-27 16:31:27 -070089#include <openssl/sha.h>
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070090#include <private/android_filesystem_config.h>
91#include <private/android_logger.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080092#include <serviceutils/PriorityDumper.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070093#include <utils/StrongPointer.h>
Devin Moore8df81bb2022-06-08 22:47:02 +000094#include <vintf/VintfObject.h>
Felipe Lemef0292972016-11-22 13:57:05 -080095#include "DumpstateInternal.h"
Felipe Leme75876a22016-10-27 16:31:27 -070096#include "DumpstateService.h"
Colin Crossf45fa6b2012-03-26 12:38:26 -070097#include "dumpstate.h"
Felipe Leme6e01fa62015-11-11 19:35:14 -080098
Kedar Chitnis9fd8c052021-11-16 09:09:22 +000099namespace dumpstate_hal_hidl_1_0 = android::hardware::dumpstate::V1_0;
100namespace dumpstate_hal_hidl = android::hardware::dumpstate::V1_1;
101namespace dumpstate_hal_aidl = aidl::android::hardware::dumpstate;
102
Vishnu Naire97d6122018-01-18 13:58:56 -0800103using ::std::literals::chrono_literals::operator""ms;
104using ::std::literals::chrono_literals::operator""s;
Rhed Jao5377d792020-07-16 17:37:39 +0800105using ::std::placeholders::_1;
Steven Morelandcb7ef822016-11-29 13:20:37 -0800106
Felipe Leme47e9be22016-12-21 15:37:07 -0800107// TODO: remove once moved to namespace
Vishnu Naire97d6122018-01-18 13:58:56 -0800108using android::defaultServiceManager;
109using android::Dumpsys;
110using android::INVALID_OPERATION;
111using android::IServiceManager;
112using android::OK;
113using android::sp;
114using android::status_t;
115using android::String16;
116using android::String8;
117using android::TIMED_OUT;
118using android::UNKNOWN_ERROR;
119using android::Vector;
Nandana Dutt979388e2018-11-30 16:48:55 +0000120using android::base::StringPrintf;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000121using android::os::IDumpstateListener;
Felipe Leme47e9be22016-12-21 15:37:07 -0800122using android::os::dumpstate::CommandOptions;
123using android::os::dumpstate::DumpFileToFd;
Rhed Jao5377d792020-07-16 17:37:39 +0800124using android::os::dumpstate::DumpPool;
Vishnu Naire97d6122018-01-18 13:58:56 -0800125using android::os::dumpstate::PropertiesHelper;
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800126using android::os::dumpstate::TaskQueue;
Chris Morinbc223142022-02-04 14:17:11 -0800127using android::os::dumpstate::WaitForTask;
Felipe Leme47e9be22016-12-21 15:37:07 -0800128
Abhijeet Kaurcf234e82019-07-01 14:53:55 +0100129// Keep in sync with
130// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
131static const int TRACE_DUMP_TIMEOUT_MS = 10000; // 10 seconds
132
133/* Most simple commands have 10 as timeout, so 5 is a good estimate */
134static const int32_t WEIGHT_FILE = 5;
135
136// TODO: temporary variables and functions used during C++ refactoring
137static Dumpstate& ds = Dumpstate::GetInstance();
138static int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Nandana Dutt8d945c02019-08-14 13:30:07 +0100139 const CommandOptions& options = CommandOptions::DEFAULT,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800140 bool verbose_duration = false, int out_fd = STDOUT_FILENO) {
141 return ds.RunCommand(title, full_command, options, verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +0100142}
143
144// Reasonable value for max stats.
145static const int STATS_MAX_N_RUNS = 1000;
146static const long STATS_MAX_AVERAGE = 100000;
147
148CommandOptions Dumpstate::DEFAULT_DUMPSYS = CommandOptions::WithTimeout(30).Build();
149
Nandana Duttd2f5f082019-01-18 17:13:52 +0000150typedef Dumpstate::ConsentCallback::ConsentResult UserConsentResult;
151
Colin Crossf45fa6b2012-03-26 12:38:26 -0700152/* read before root is shed */
153static char cmdline_buf[16384] = "(unknown)";
Yi Kong19d5c002018-07-20 13:39:55 -0700154static const char *dump_traces_path = nullptr;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000155static const uint64_t USER_CONSENT_TIMEOUT_MS = 30 * 1000;
Hunter Knepshield70610fa2020-01-03 15:27:33 -0800156// 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.
160static const uint64_t TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS = 2 * 60 * 1000;
Colin Crossf45fa6b2012-03-26 12:38:26 -0700161
Felipe Leme1d486fe2016-10-14 18:06:47 -0700162// TODO: variables and functions below should be part of dumpstate object
163
Felipe Leme635ca312016-01-05 14:23:02 -0800164static std::set<std::string> mount_points;
165void add_mountinfo();
Felipe Leme78f2c862015-12-21 09:55:22 -0800166
Todd Poynor2a83daa2013-11-22 15:44:22 -0800167#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
Mark Salyzyn7d0a7622016-06-24 14:06:15 -0700168#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
Wei Wang509bb5d2017-06-09 14:42:12 -0700169#define BLK_DEV_SYS_DIR "/sys/block"
Todd Poynor2a83daa2013-11-22 15:44:22 -0800170
Felipe Lemee82a27d2016-01-05 13:35:44 -0800171#define RECOVERY_DIR "/cache/recovery"
Mark Salyzynd6ab0112016-03-25 12:56:39 -0700172#define RECOVERY_DATA_DIR "/data/misc/recovery"
Tianjie Xu75d53362018-04-11 16:42:28 -0700173#define UPDATE_ENGINE_LOG_DIR "/data/misc/update_engine_log"
Kelvin Zhang6eaa0f92022-09-12 09:29:19 -0700174#define UPDATE_ENGINE_PREF_DIR "/data/misc/update_engine/prefs"
Mark Salyzyn4d42dea2016-04-01 10:03:14 -0700175#define LOGPERSIST_DATA_DIR "/data/misc/logd"
Jerry Changa1df8a92020-01-02 16:03:39 +0800176#define PREREBOOT_DATA_DIR "/data/misc/prereboot"
David Brazdild2991962016-06-03 14:40:44 +0100177#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
178#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
Benedict Wong8f9d8a42019-01-03 16:19:38 -0800179#define XFRM_STAT_PROC_FILE "/proc/net/xfrm_stat"
Erik Kline08165202016-05-30 11:55:44 +0900180#define WLUTIL "/vendor/xbin/wlutil"
Vishnu Nair36b4cdb2017-11-17 10:27:05 -0800181#define WMTRACE_DATA_DIR "/data/misc/wmtrace"
Yifan Hong3945e1b2019-10-29 12:59:23 -0700182#define OTA_METADATA_DIR "/metadata/ota"
Yifan Hong0efa7972020-02-03 16:45:02 -0800183#define SNAPSHOTCTL_LOG_DIR "/data/misc/snapshotctl_log"
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +0900184#define LINKERCONFIG_DIR "/linkerconfig"
Calin Juravlef84d3692020-04-28 15:31:12 -0700185#define PACKAGE_DEX_USE_LIST "/data/system/package-dex-usage.list"
Primiano Tuccifaaaafb2021-01-14 12:26:29 +0000186#define SYSTEM_TRACE_SNAPSHOT "/data/misc/perfetto-traces/bugreport/systrace.pftrace"
Li Li2eedd412021-06-30 15:11:53 -0700187#define CGROUPFS_DIR "/sys/fs/cgroup"
Mårten Kongstad60195a72022-09-20 14:14:20 +0200188#define SDK_EXT_INFO "/apex/com.android.sdkext/bin/derive_sdk"
Jeff Sharkey9df29d52023-02-06 14:26:30 -0700189#define DROPBOX_DIR "/data/system/dropbox"
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700190
Narayan Kamath8f788292017-05-25 13:20:39 +0100191// 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
Narayan Kamathbd863722017-06-01 18:50:12 +0100195static const std::string TOMBSTONE_DIR = "/data/tombstones/";
196static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
197static const std::string ANR_DIR = "/data/anr/";
198static const std::string ANR_FILE_PREFIX = "anr_";
Woody Lin20767a92022-11-29 15:50:24 +0800199static const std::string SHUTDOWN_CHECKPOINTS_DIR = "/data/system/shutdown-checkpoints/";
200static const std::string SHUTDOWN_CHECKPOINTS_FILE_PREFIX = "checkpoints-";
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700201
Felipe Lemee844a9d2016-09-21 15:01:39 -0700202// TODO: temporary variables and functions used during C++ refactoring
Nandana Dutt979388e2018-11-30 16:48:55 +0000203
Nandana Dutt5c390032019-03-12 10:52:56 +0000204#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
Rhed Jao5377d792020-07-16 17:37:39 +0800217// 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
Chris Morinbc223142022-02-04 14:17:11 -0800231#define WAIT_TASK_WITH_CONSENT_CHECK(future) \
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800232 RETURN_IF_USER_DENIED_CONSENT(); \
Chris Morinbc223142022-02-04 14:17:11 -0800233 WaitForTask(future); \
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800234 RETURN_IF_USER_DENIED_CONSENT();
235
Sahana Raof35ed432019-07-12 10:47:52 +0100236static const char* WAKE_LOCK_NAME = "dumpstate_wakelock";
237
Rhed Jao5377d792020-07-16 17:37:39 +0800238// Names of parallel tasks, they are used for the DumpPool to identify the dump
239// task and the log title of the duration report.
240static const std::string DUMP_TRACES_TASK = "DUMP TRACES";
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800241static const std::string DUMP_INCIDENT_REPORT_TASK = "INCIDENT REPORT";
Aaron Huang24d215d2022-04-27 18:51:16 +0800242static const std::string DUMP_NETSTATS_PROTO_TASK = "DUMP NETSTATS PROTO";
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800243static const std::string DUMP_HALS_TASK = "DUMP HALS";
244static const std::string DUMP_BOARD_TASK = "dumpstate_board()";
Rhed Jaoe017f982020-07-21 17:58:41 +0800245static const std::string DUMP_CHECKINS_TASK = "DUMP CHECKINS";
Kean Mariotti306633e2022-09-05 16:30:47 +0000246static const std::string POST_PROCESS_UI_TRACES_TASK = "POST-PROCESS UI TRACES";
Rhed Jao5377d792020-07-16 17:37:39 +0800247
Nandana Dutt979388e2018-11-30 16:48:55 +0000248namespace android {
249namespace os {
250namespace {
251
252static 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
mhasank2d75c442020-06-11 15:05:25 -0700260static 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}
Nandana Dutt979388e2018-11-30 16:48:55 +0000264
265static int OpenForRead(std::string path) {
266 return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
267}
268
269bool 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
280static bool CopyFileToFd(const std::string& input_file, int out_fd) {
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000281 MYLOGD("Going to copy file (%s) to %d\n", input_file.c_str(), out_fd);
Nandana Dutt979388e2018-11-30 16:48:55 +0000282
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 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000289 MYLOGE("Failed to copy file: %s\n", strerror(errno));
Nandana Dutt979388e2018-11-30 16:48:55 +0000290 }
291 return false;
292}
293
Nandana Duttd2f5f082019-01-18 17:13:52 +0000294static bool UnlinkAndLogOnError(const std::string& file) {
Nandana Dutt8ae16e62020-03-27 10:20:22 +0000295 if (file.empty()) {
296 return false;
297 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000298 if (unlink(file.c_str())) {
299 MYLOGE("Failed to unlink file (%s): %s\n", file.c_str(), strerror(errno));
Nandana Duttd2f5f082019-01-18 17:13:52 +0000300 return false;
301 }
302 return true;
303}
Nandana Dutt979388e2018-11-30 16:48:55 +0000304
Nikita Ioffea325a572019-05-16 19:49:47 +0100305int64_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 }
Nandana Duttdb379fa2019-10-09 16:54:41 +0100318 MYLOGD("Module metadata package name: %s\n", package_name.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100319 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
mhasank2d75c442020-06-11 15:05:25 -0700329static bool PathExists(const std::string& path) {
330 struct stat sb;
331 return stat(path.c_str(), &sb) == 0;
332}
333
334static 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
Nandana Dutt979388e2018-11-30 16:48:55 +0000350} // namespace
351} // namespace os
352} // namespace android
353
Felipe Leme678727a2016-09-21 17:22:11 -0700354static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
Felipe Lemebda15a02016-11-16 17:48:25 -0800355 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
Rhed Jaoe017f982020-07-21 17:58:41 +0800356 long dumpsysTimeoutMs = 0, int out_fd = STDOUT_FILENO) {
357 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs, out_fd);
358}
359static 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);
Felipe Leme678727a2016-09-21 17:22:11 -0700362}
363static int DumpFile(const std::string& title, const std::string& path) {
364 return ds.DumpFile(title, path);
365}
Felipe Lemee82a27d2016-01-05 13:35:44 -0800366
Felipe Lemee844a9d2016-09-21 15:01:39 -0700367// Relative directory (inside the zip) for all files copied as-is into the bugreport.
368static const std::string ZIP_ROOT_DIR = "FS";
369
Vishnu Naire97d6122018-01-18 13:58:56 -0800370static const std::string kProtoPath = "proto/";
371static const std::string kProtoExt = ".proto";
Jie Song9fbfad02017-06-20 16:29:42 -0700372static const std::string kDumpstateBoardFiles[] = {
373 "dumpstate_board.txt",
Felipe Leme95d6ca52017-08-01 16:35:56 -0700374 "dumpstate_board.bin"
Jie Song9fbfad02017-06-20 16:29:42 -0700375};
376static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
377
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700378static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Lemed071c682016-10-20 16:48:00 -0700379static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700380
Felipe Lemef0292972016-11-22 13:57:05 -0800381static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
382
Narayan Kamath8f788292017-05-25 13:20:39 +0100383/*
Narayan Kamathbd863722017-06-01 18:50:12 +0100384 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
Rhed Jao01dc0c62020-06-03 17:13:30 +0800385 * The returned vector is sorted by the mtimes of the dumps with descending
Chris Morinc2cba7a2022-02-01 17:06:50 -0800386 * order.
Narayan Kamath8f788292017-05-25 13:20:39 +0100387 */
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700388static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
Chris Morinc2cba7a2022-02-01 17:06:50 -0800389 const std::string& file_prefix) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100390 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100391
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700392 if (dump_dir == nullptr) {
393 MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno));
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700394 return std::vector<DumpData>();
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700395 }
396
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700397 std::vector<DumpData> dump_data;
Narayan Kamathbd863722017-06-01 18:50:12 +0100398 struct dirent* entry = nullptr;
399 while ((entry = readdir(dump_dir.get()))) {
400 if (entry->d_type != DT_REG) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100401 continue;
402 }
403
Narayan Kamathbd863722017-06-01 18:50:12 +0100404 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) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700413 MYLOGW("Unable to open dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamathbd863722017-06-01 18:50:12 +0100414 break;
415 }
416
417 struct stat st = {};
418 if (fstat(fd, &st) == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700419 MYLOGW("Unable to stat dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamath8f788292017-05-25 13:20:39 +0100420 continue;
421 }
422
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700423 dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700424 }
Rhed Jao01dc0c62020-06-03 17:13:30 +0800425 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 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100429
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700430 return dump_data;
Narayan Kamath8f788292017-05-25 13:20:39 +0100431}
432
Narayan Kamathbd863722017-06-01 18:50:12 +0100433static 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) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100436 bool dumped = false;
Narayan Kamathbd863722017-06-01 18:50:12 +0100437 for (auto it = start; it != end; ++it) {
438 const std::string& name = it->name;
439 const int fd = it->fd;
Narayan Kamath8f788292017-05-25 13:20:39 +0100440 dumped = true;
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100441
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
Chris Morinc2cba7a2022-02-01 17:06:50 -0800453 if (add_to_zip) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800454 if (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd, /* timeout = */ 0ms) != OK) {
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100455 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100456 }
457 } else {
458 dump_file_from_fd(type_name, name.c_str(), fd);
459 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100460 }
461
462 return dumped;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700463}
464
Felipe Leme635ca312016-01-05 14:23:02 -0800465// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700466void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800467 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.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700471 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800472 char linkname[PATH_MAX];
473 ssize_t r = readlink(path, linkname, PATH_MAX);
474 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800475 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800476 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
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700482 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700483 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
Felipe Leme635ca312016-01-05 14:23:02 -0800484 mount_points.insert(linkname);
485 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800486 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800487 }
488 }
489}
490
491void add_mountinfo() {
Felipe Leme678727a2016-09-21 17:22:11 -0700492 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800493 mount_points.clear();
Felipe Leme46b85da2016-11-21 17:40:45 -0800494 DurationReporter duration_reporter(title, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700495 for_each_pid(do_mountinfo, nullptr);
496 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800497}
498
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700499static 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);
Yi Kong19d5c002018-07-20 13:39:55 -0700506 if (d == nullptr) {
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700507 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);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700515 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700516 }
517
518 closedir(d);
519}
520
Mark Salyzyn326842f2015-04-30 09:49:41 -0700521static 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
Jeff Sharkey9df29d52023-02-06 14:26:30 -0700530static 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
Felipe Leme4c2d6632016-09-28 14:32:00 -0700539static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800540 return false;
541}
542
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700543unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700544
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800545//
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
Mark Salyzyn326842f2015-04-30 09:49:41 -0700625static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800626 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700627 bool z;
Yi Kong19d5c002018-07-20 13:39:55 -0700628 char *cp, *buffer = nullptr;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700629 size_t i = 0;
Josh Gao7c4258c2018-06-25 13:40:08 -0700630 FILE *fp = fdopen(dup(fd), "rb");
Mark Salyzyn326842f2015-04-30 09:49:41 -0700631 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) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800646 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700647 if (fields[i] != 0) {
648 z = false;
649 }
650 }
651 if (z) { /* never accessed */
652 free(buffer);
653 return 0;
654 }
655
Wei Wang509bb5d2017-06-09 14:42:12 -0700656 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
657 path += sizeof(BLK_DEV_SYS_DIR) - 1;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700658 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700659
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);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700663 free(buffer);
664
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800665 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) {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700699 printf("%-30s: perf(ios) rd: %luKB/s(%lu/s) q: %u\n", path, read_perf, read_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800700 } else {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700701 printf("%-30s: perf(ios) rd: %luKB/s(%lu/s) wr: %luKB/s(%lu/s) q: %u\n", path, read_perf,
Felipe Lemed8b94e52016-12-08 10:21:44 -0800702 read_ios, write_perf, write_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800703 }
704
705 /* bugreport timeout factor adjustment */
706 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
707 worst_write_perf = write_perf;
708 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700709 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700710 return 0;
711}
712
Yao Chenbe3bbc12018-01-17 16:31:10 -0800713static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
714
Tom Cherryf4472f32020-08-05 09:31:17 -0700715// Returns the actual readable size of the given buffer or -1 on error.
716static 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.
Yao Chenbe3bbc12018-01-17 16:31:10 -0800725static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
726 unsigned long timeout_ms = 0;
727 for (const auto& buffer : buffers) {
Tom Cherryf4472f32020-08-05 09:31:17 -0700728 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 }
Yao Chenbe3bbc12018-01-17 16:31:10 -0800733 }
734 return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700735}
736
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800737// Opens a socket and returns its file descriptor.
738static int open_socket(const char* service);
739
Nandana Duttd2f5f082019-01-18 17:13:52 +0000740Dumpstate::ConsentCallback::ConsentCallback() : result_(UNAVAILABLE), start_time_(Nanotime()) {
741}
742
743android::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");
Paul Chang0d2aad72020-02-13 20:04:03 +0800747
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 }
Nandana Duttd2f5f082019-01-18 17:13:52 +0000765 return android::binder::Status::ok();
766}
767
768android::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
775UserConsentResult Dumpstate::ConsentCallback::getResult() {
776 std::lock_guard<std::mutex> lock(lock_);
777 return result_;
778}
779
780uint64_t Dumpstate::ConsentCallback::getElapsedTimeMs() const {
Hunter Knepshieldf0a39052020-01-03 14:53:04 -0800781 return (Nanotime() - start_time_) / NANOS_PER_MILLI;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000782}
783
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700784void Dumpstate::PrintHeader() const {
Mårten Kongstad60195a72022-09-20 14:14:20 +0200785 std::string build, fingerprint, radio, bootloader, network, sdkversion;
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700786 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700787
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700788 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
789 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700790 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)");
Mårten Kongstad60195a72022-09-20 14:14:20 +0200793 sdkversion = android::base::GetProperty("ro.build.version.sdk", "(unknown)");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700794 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
Colin Crossf45fa6b2012-03-26 12:38:26 -0700795
Felipe Lemed8b94e52016-12-08 10:21:44 -0800796 printf("========================================================\n");
797 printf("== dumpstate: %s\n", date);
798 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700799
Felipe Lemed8b94e52016-12-08 10:21:44 -0800800 printf("\n");
801 printf("Build: %s\n", build.c_str());
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700802 // NOTE: fingerprint entry format is important for other tools.
Felipe Lemed8b94e52016-12-08 10:21:44 -0800803 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());
Nikita Ioffea325a572019-05-16 19:49:47 +0100807 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 }
Mårten Kongstad60195a72022-09-20 14:14:20 +0200811 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());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700815
Felipe Lemed8b94e52016-12-08 10:21:44 -0800816 printf("Kernel: ");
Felipe Lemef0292972016-11-22 13:57:05 -0800817 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
Felipe Lemed8b94e52016-12-08 10:21:44 -0800818 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
Devin Moore09fde8d2023-03-21 16:28:22 +0000819 printf("Bootconfig: ");
820 DumpFileToFd(STDOUT_FILENO, "", "/proc/bootconfig");
Felipe Leme7709f8a2017-12-05 09:30:09 -0800821 printf("Uptime: ");
822 RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"},
823 CommandOptions::WithTimeout(1).Always().Build());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800824 printf("Bugreport format version: %s\n", version_.c_str());
Kevin Jeonfa64e642023-07-27 11:36:41 -0400825 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());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800831 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800832}
833
Felipe Leme24b66ee2016-06-16 10:55:26 -0700834// List of file extensions that can cause a zip file attachment to be rejected by some email
835// service providers.
836static 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
Vishnu Naire97d6122018-01-18 13:58:56 -0800842status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd,
843 std::chrono::milliseconds timeout = 0ms) {
Felipe Leme24b66ee2016-06-16 10:55:26 -0700844 std::string valid_name = entry_name;
845
846 // Rename extension if necessary.
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -0700847 size_t idx = entry_name.rfind('.');
Felipe Leme24b66ee2016-06-16 10:55:26 -0700848 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
Felipe Leme6fe9db62016-02-12 09:04:16 -0800857 // 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());
Kevin Jeon9bbe0ac2022-05-05 22:05:43 +0000859 size_t flags = ZipWriter::kCompress | ZipWriter::kDefaultCompression;
860 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), flags,
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700861 get_mtime(fd, ds.now_));
Felipe Leme1d486fe2016-10-14 18:06:47 -0700862 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700863 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700864 ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800865 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800866 }
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000867 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);
Vishnu Naire97d6122018-01-18 13:58:56 -0800878 auto start = std::chrono::steady_clock::now();
879 auto end = start + timeout;
880 struct pollfd pfd = {fd, POLLIN};
Felipe Lemee82a27d2016-01-05 13:35:44 -0800881
Felipe Leme770410d2016-01-26 17:07:14 -0800882 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800883 while (1) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800884 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) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000894 MYLOGE("Error in poll while adding from fd to zip entry %s:%s\n",
895 entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800896 return -errno;
897 } else if (rc == 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000898 MYLOGE("Timed out adding from fd to zip entry %s:%s Timeout:%lldms\n",
Vishnu Naire97d6122018-01-18 13:58:56 -0800899 entry_name.c_str(), strerror(errno), timeout.count());
900 return TIMED_OUT;
901 }
902 }
903
Zach Riggle22200402016-08-18 01:01:24 -0400904 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800905 if (bytes_read == 0) {
906 break;
907 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800908 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800909 return -errno;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800910 }
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700911 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800912 if (err) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700913 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800914 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800915 }
916 }
917
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700918 err = zip_writer_->FinishEntry();
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000919 finished_entry = true;
Felipe Leme1d486fe2016-10-14 18:06:47 -0700920 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700921 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800922 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800923 }
924
Vishnu Naire97d6122018-01-18 13:58:56 -0800925 return OK;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800926}
927
Felipe Leme1d486fe2016-10-14 18:06:47 -0700928bool 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)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700931 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800932 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800933 return false;
934 }
935
Vishnu Naire97d6122018-01-18 13:58:56 -0800936 return (AddZipEntryFromFd(entry_name, fd.get()) == OK);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800937}
938
939/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700940static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800941 return (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) == OK) ? 0 : 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800942}
943
Felipe Leme1d486fe2016-10-14 18:06:47 -0700944void Dumpstate::AddDir(const std::string& dir, bool recursive) {
Felipe Leme678727a2016-09-21 17:22:11 -0700945 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
Felipe Leme46b85da2016-11-21 17:40:45 -0800946 DurationReporter duration_reporter(dir, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700947 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800948}
949
Felipe Leme1d486fe2016-10-14 18:06:47 -0700950bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800951 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Kevin Jeon9bbe0ac2022-05-05 22:05:43 +0000952 size_t flags = ZipWriter::kCompress | ZipWriter::kDefaultCompression;
953 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), flags, ds.now_);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700954 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700955 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700956 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800957 return false;
958 }
959
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700960 err = zip_writer_->WriteBytes(content.c_str(), content.length());
Felipe Leme1d486fe2016-10-14 18:06:47 -0700961 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700962 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700963 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800964 return false;
965 }
966
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700967 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700968 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700969 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800970 return false;
971 }
972
973 return true;
974}
975
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800976static 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
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800989static void DoKernelLogcat() {
Yao Chenbe3bbc12018-01-17 16:31:10 -0800990 unsigned long timeout_ms = logcat_timeout({"kernel"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800991 RunCommand(
992 "KERNEL LOG",
993 {"logcat", "-b", "kernel", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
994 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
995}
996
Nandana Duttdb379fa2019-10-09 16:54:41 +0100997static 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
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001008static 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
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001016static void DoLogcat() {
Vishnu Nair6921f802017-11-22 09:17:23 -08001017 unsigned long timeout_ms;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001018 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
1019 // calculate timeout
Yao Chenbe3bbc12018-01-17 16:31:10 -08001020 timeout_ms = logcat_timeout({"main", "system", "crash"});
Tony Makae737652017-03-30 17:47:09 +01001021 RunCommand("SYSTEM LOG",
Vishnu Nair6921f802017-11-22 09:17:23 -08001022 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1023 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -08001024 timeout_ms = logcat_timeout({"events"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001025 RunCommand(
1026 "EVENT LOG",
1027 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001028 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Yao Chenbe3bbc12018-01-17 16:31:10 -08001029 timeout_ms = logcat_timeout({"stats"});
1030 RunCommand(
1031 "STATS LOG",
1032 {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001033 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001034 DoRadioLogcat();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001035
1036 RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
1037
1038 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001039 RunCommand("LAST LOGCAT", {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable",
1040 "-v", "uid", "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001041}
1042
Mike Ma5c267872019-08-21 11:31:34 -07001043static void DumpIncidentReport() {
Mike Ma5c267872019-08-21 11:31:34 -07001044 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 }
Kevin Jeonfa64e642023-07-27 11:36:41 -04001052 RunCommandToFd(fd, "", {"incident", "-u"},
1053 CommandOptions::WithTimeout(PropertiesHelper::IsStrictRun() ? 20 : 120).Build());
Mike Ma5c267872019-08-21 11:31:34 -07001054 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.
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001059 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "incident_report" + kProtoExt,
1060 path);
1061 } else {
1062 unlink(path.c_str());
Mike Ma5c267872019-08-21 11:31:34 -07001063 }
Mike Ma5c267872019-08-21 11:31:34 -07001064}
1065
Aaron Huang24d215d2022-04-27 18:51:16 +08001066static 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"},
Kevin Jeon2fb3dd62022-09-28 18:48:55 +00001076 CommandOptions::WithTimeout(5).Build());
Aaron Huang24d215d2022-04-27 18:51:16 +08001077 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
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001086static 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.
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001090 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
Sunny Goyal35949782019-11-19 15:54:36 -08001100static void DumpVisibleWindowViews() {
Sunny Goyal35949782019-11-19 15:54:36 -08001101 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"},
Kevin Jeon774abde2022-09-28 18:20:43 +00001111 CommandOptions::WithTimeout(10).Build());
Sunny Goyal35949782019-11-19 15:54:36 -08001112 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
Jayachandran Ca94c7172017-06-10 15:08:12 -07001121static void DumpIpTablesAsRoot() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001122 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
1123 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +09001124 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001125 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +09001126 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"});
Felipe Lemec0808152016-06-17 17:37:13 -07001130}
1131
Woody Lin20767a92022-11-29 15:50:24 +08001132static 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
David Andersond9ba4752018-12-11 18:26:59 -08001142static void DumpDynamicPartitionInfo() {
1143 if (!::android::base::GetBoolProperty("ro.boot.dynamic_partitions", false)) {
1144 return;
1145 }
1146
1147 RunCommand("LPDUMP", {"lpdump", "--all"});
David Anderson6650ade2019-10-02 15:18:59 -07001148 RunCommand("DEVICE-MAPPER", {"gsid", "dump-device-mapper"});
David Andersond9ba4752018-12-11 18:26:59 -08001149}
1150
Chris Morin5a50d482022-02-01 17:41:18 -08001151static void AddAnrTraceDir(const std::string& anr_traces_dir) {
Narayan Kamath8f788292017-05-25 13:20:39 +01001152 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) {
Chris Morin5a50d482022-02-01 17:41:18 -08001159 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);
Narayan Kamath8f788292017-05-25 13:20:39 +01001162
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));
Felipe Lemee184f662016-10-27 10:04:47 -07001167 }
1168 }
1169
Narayan Kamathbd863722017-06-01 18:50:12 +01001170 // Add a specific message for the first ANR Dump.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001171 if (ds.anr_data_.size() > 0) {
Chris Morin5a50d482022-02-01 17:41:18 -08001172 // The "last" ANR will always be present in the body of the main entry.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001173 AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1,
Chris Morin5a50d482022-02-01 17:41:18 -08001174 "VM TRACES AT LAST ANR", false /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001175
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001176 // Historical ANRs are always included as separate entries in the bugreport zip file.
Chris Morin5a50d482022-02-01 17:41:18 -08001177 AddDumps(ds.anr_data_.begin(), ds.anr_data_.end(),
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001178 "HISTORICAL ANR", true /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001179 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +01001180 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
1181 }
1182}
1183
1184static void AddAnrTraceFiles() {
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001185 std::string anr_traces_dir = "/data/anr";
Narayan Kamath8f788292017-05-25 13:20:39 +01001186
Chris Morin5a50d482022-02-01 17:41:18 -08001187 AddAnrTraceDir(anr_traces_dir);
Narayan Kamath8f788292017-05-25 13:20:39 +01001188
Makoto Onuki83ec63f2019-01-31 17:08:59 -08001189 RunCommand("ANR FILES", {"ls", "-lt", ANR_DIR});
1190
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001191 // Slow traces for slow operations.
Felipe Lemee184f662016-10-27 10:04:47 -07001192 struct stat st;
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001193 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;
Felipe Lemee184f662016-10-27 10:04:47 -07001200 }
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001201 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
1202 i++;
Felipe Lemee184f662016-10-27 10:04:47 -07001203 }
1204}
1205
Wei Wang509bb5d2017-06-09 14:42:12 -07001206static void DumpBlockStatFiles() {
1207 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -07001208
Wei Wang1dc1ef52017-06-12 11:28:37 -07001209 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
1210
1211 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001212 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1213 return;
1214 }
1215
1216 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -07001217 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001218 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 }
Wei Wang1dc1ef52017-06-12 11:28:37 -07001229 return;
Wei Wang509bb5d2017-06-09 14:42:12 -07001230}
Jayachandran Ca94c7172017-06-10 15:08:12 -07001231
1232static void DumpPacketStats() {
1233 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
Jayachandran Ca94c7172017-06-10 15:08:12 -07001234}
1235
1236static 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
Nandana Dutt5c390032019-03-12 10:52:56 +00001245static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, int priority,
1246 std::chrono::milliseconds timeout,
1247 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001248 auto start = std::chrono::steady_clock::now();
Vishnu Naire97d6122018-01-18 13:58:56 -08001249 sp<android::IServiceManager> sm = defaultServiceManager();
1250 Dumpsys dumpsys(sm.get());
Vishnu Naire97d6122018-01-18 13:58:56 -08001251 Vector<String16> args;
1252 Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
Vishnu Naire97d6122018-01-18 13:58:56 -08001253 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1254 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001255 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001256 std::string path(title);
1257 path.append(" - ").append(String8(service).c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -08001258 size_t bytes_written = 0;
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001259 if (PropertiesHelper::IsDryRun()) {
1260 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1261 dumpsys.writeDumpFooter(STDOUT_FILENO, service, std::chrono::milliseconds(1));
1262 } else {
Devin Mooref492c1a2023-03-15 19:19:03 +00001263 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP | Dumpsys::TYPE_PID |
1264 Dumpsys::TYPE_CLIENTS | Dumpsys::TYPE_THREAD,
Devin Mooreae68df22023-02-24 20:59:51 +00001265 service, args);
1266 if (status == OK) {
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001267 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);
Devin Moorecdfa4602023-03-16 20:49:39 +00001283 } else {
1284 MYLOGE("Failed to start dump thread for service: %s, status: %d",
1285 String8(service).c_str(), status);
Gavin Corkeryfac7e2b2021-07-08 22:39:02 +01001286 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001287 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001288
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 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001297 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001298}
1299
Vishnu Nair64afc022018-02-01 15:29:34 -08001300static 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. */
Nandana Dutt5c390032019-03-12 10:52:56 +00001310static Dumpstate::RunStatus RunDumpsysTextNormalPriority(const std::string& title,
1311 std::chrono::milliseconds timeout,
1312 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001313 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);
Nandana Dutt5c390032019-03-12 10:52:56 +00001318
1319 RETURN_IF_USER_DENIED_CONSENT();
1320
1321 return RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1322 service_timeout);
Vishnu Nair64afc022018-02-01 15:29:34 -08001323}
1324
Nandana Dutt5c390032019-03-12 10:52:56 +00001325static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priority,
1326 std::chrono::milliseconds timeout,
1327 std::chrono::milliseconds service_timeout) {
Vishnu Naire97d6122018-01-18 13:58:56 -08001328 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) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001337 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001338 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);
Steven Morelandcbd69fc2021-07-20 20:45:43 +00001346 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP, service, args);
Vishnu Naire97d6122018-01-18 13:58:56 -08001347 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);
Vishnu Naire97d6122018-01-18 13:58:56 -08001354
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 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001363 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001364}
1365
Nandana Dutta7db6342018-11-21 14:53:34 +00001366// Runs dumpsys on services that must dump first and will take less than 100ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001367static Dumpstate::RunStatus RunDumpsysCritical() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001368 RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1369 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Nandana Dutt5c390032019-03-12 10:52:56 +00001370
1371 RETURN_IF_USER_DENIED_CONSENT();
1372
1373 return RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1374 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Vishnu Nair780b1282017-10-10 13:57:24 -07001375}
1376
1377// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001378static Dumpstate::RunStatus RunDumpsysHigh() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001379 // 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);
Nandana Dutt5c390032019-03-12 10:52:56 +00001384
1385 RETURN_IF_USER_DENIED_CONSENT();
1386
1387 return RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1388 /* timeout= */ 5s, /* service_timeout= */ 1s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001389}
1390
1391// Runs dumpsys on services that must dump but can take up to 10s to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001392static Dumpstate::RunStatus RunDumpsysNormal() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001393 RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001394
1395 RETURN_IF_USER_DENIED_CONSENT();
1396
1397 return RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1398 /* timeout= */ 90s, /* service_timeout= */ 10s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001399}
1400
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001401/*
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 */
1406static void DumpHals(int out_fd = STDOUT_FILENO) {
Yifan Hong30528a22020-08-07 18:24:06 -07001407 RunCommand("HARDWARE HALS", {"lshal", "--all", "--types=all"},
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001408 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build(),
1409 false, out_fd);
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001410
Steven Moreland44cd9482018-01-04 16:24:13 -08001411 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;
Steven Morelandc6b1fc22023-07-26 23:53:58 +00001423 std::replace_if(
1424 cleanName.begin(), cleanName.end(),
1425 [](char c) {
1426 return !isalnum(c) && std::string("@-_.").find(c) == std::string::npos;
1427 },
1428 '_');
Nandana Dutt979388e2018-11-30 16:48:55 +00001429 const std::string path = ds.bugreport_internal_dir_ + "/lshal_debug_" + cleanName;
Steven Moreland44cd9482018-01-04 16:24:13 -08001430
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001431 bool empty = false;
Steven Moreland44cd9482018-01-04 16:24:13 -08001432 {
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 "",
Steven Morelandc81cd3c2018-01-18 14:36:26 -08001443 {"lshal", "debug", "-E", interface},
Steven Moreland44cd9482018-01-04 16:24:13 -08001444 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1445
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001446 empty = 0 == lseek(fd, 0, SEEK_END);
Steven Moreland44cd9482018-01-04 16:24:13 -08001447 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001448 if (!empty) {
1449 ds.EnqueueAddZipEntryAndCleanupIfNeeded("lshal-debug/" + cleanName + ".txt",
1450 path);
1451 } else {
1452 unlink(path.c_str());
1453 }
Steven Moreland44cd9482018-01-04 16:24:13 -08001454 }
1455 });
1456
1457 if (!ret.isOk()) {
1458 MYLOGE("Could not list hals from hwservicemanager.\n");
1459 }
1460}
1461
Devin Moore8df81bb2022-06-08 22:47:02 +00001462// Dump all of the files that make up the vendor interface.
1463// See the files listed in dumpFileList() for the latest list of files.
1464static void DumpVintf() {
Devin Moore16271d92022-09-22 18:28:48 +00001465
1466 const std::string sku = android::base::GetProperty("ro.boot.product.hardware.sku", "");
1467 const auto vintfFiles = android::vintf::details::dumpFileList(sku);
Devin Moore8df81bb2022-06-08 22:47:02 +00001468 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
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001481static 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
mhasankd451a472020-05-26 18:02:39 -07001520static 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));
Hugo Benichiaa162682020-10-30 23:28:56 +09001544 RunDumpsys("DUMPSYS CONNECTIVITY REQUESTS", {"connectivity", "requests"},
1545 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
mhasankd451a472020-05-26 18:02:39 -07001546
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
Rhed Jaoe017f982020-07-21 17:58:41 +08001562/*
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 */
1567static 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);
Rhed Jaoe017f982020-07-21 17:58:41 +08001573 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 */
1587static 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"},
Rhed Jaob049f182021-01-11 21:08:43 +08001618 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001619
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
Nandana Dutt5c390032019-03-12 10:52:56 +00001628// 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.
Kean Mariotti306633e2022-09-05 16:30:47 +00001632Dumpstate::RunStatus Dumpstate::dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001633 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001634
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001635 // Enqueue slow functions into the thread pool, if the parallel run is enabled.
Aaron Huang24d215d2022-04-27 18:51:16 +08001636 std::future<std::string> dump_hals, dump_incident_report, dump_board, dump_checkins,
Kean Mariotti306633e2022-09-05 16:30:47 +00001637 dump_netstats_report, post_process_ui_traces;
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001638 if (ds.dump_pool_) {
1639 // Pool was shutdown in DumpstateDefaultAfterCritical method in order to
Kean Mariotti306633e2022-09-05 16:30:47 +00001640 // drop root user. Restarts it.
1641 ds.dump_pool_->start(/* thread_counts = */3);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001642
Chris Morinbc223142022-02-04 14:17:11 -08001643 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);
Aaron Huang24d215d2022-04-27 18:51:16 +08001646 dump_netstats_report = ds.dump_pool_->enqueueTask(
1647 DUMP_NETSTATS_PROTO_TASK, &DumpNetstatsProto);
Chris Morinbc223142022-02-04 14:17:11 -08001648 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);
Kean Mariotti306633e2022-09-05 16:30:47 +00001651 post_process_ui_traces = ds.dump_pool_->enqueueTask(
1652 POST_PROCESS_UI_TRACES_TASK, &Dumpstate::MaybePostProcessUiTraces, &ds);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001653 }
1654
Nandana Dutt5c390032019-03-12 10:52:56 +00001655 // 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).
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001658 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001659 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001660 DumpBlockStatFiles();
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001661 DumpFile("MEMORY INFO", "/proc/meminfo");
1662 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001663 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001664
Kevin Jeon947922b2022-09-21 00:29:18 +00001665 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "BUGREPORT_PROCDUMP", {"bugreport_procdump"},
1666 CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001667
Sunny Goyal35949782019-11-19 15:54:36 -08001668 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpVisibleWindowViews);
1669
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001670 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");
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001676 DumpExternalFragmentationInfo();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001677
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001678 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001679
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001680 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001681 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001682
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001683 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001684 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_hals));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001685 } else {
1686 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_HALS_TASK, DumpHals);
1687 }
Steven Moreland81b429e2017-01-31 19:50:46 -08001688
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001689 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001690 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001691 struct stat s;
1692 if (stat("/proc/modules", &s) != 0) {
1693 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1694 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001695 RunCommand("LSMOD", {"lsmod"});
Woody Linc198f252021-05-04 16:37:11 +08001696 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);
Felipe Lemee4eca582016-06-10 17:48:08 -07001700 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001701
Tom Cherryb87dbfa2020-07-28 11:28:53 -07001702 if (android::base::GetBoolProperty("ro.logd.kernel", false)) {
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001703 DoKernelLogcat();
1704 } else {
1705 do_dmesg();
1706 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001707
Devin Moore8df81bb2022-06-08 22:47:02 +00001708 DumpVintf();
1709
Felipe Lemef0292972016-11-22 13:57:05 -08001710 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001711
Jeff Brown1dc94e32014-09-11 14:15:27 -07001712 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001713 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001714
Jack Yu5a6b2e22020-08-14 18:13:35 +08001715 /* Dump Nfc NCI logs */
1716 ds.AddDir("/data/misc/nfc/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001717
Paul Chang0d2aad72020-02-13 20:04:03 +08001718 if (ds.options_->do_screenshot && !ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001719 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001720 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001721 }
1722
Felipe Lemee184f662016-10-27 10:04:47 -07001723 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001724
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001725 MaybeAddSystemTraceToZip();
1726
Narayan Kamath8f788292017-05-25 13:20:39 +01001727 // NOTE: tombstones are always added as separate entries in the zip archive
1728 // and are not interspersed with the main report.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001729 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
Narayan Kamathbd863722017-06-01 18:50:12 +01001730 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001731 if (!tombstones_dumped) {
1732 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001733 }
1734
Jayachandran Ca94c7172017-06-10 15:08:12 -07001735 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001736
Lorenzo Colitti807f2dd2022-05-27 12:48:37 +09001737 RunDumpsys("EBPF MAP STATS", {"connectivity", "trafficcontroller"});
Chenbo Feng276a3b62018-08-07 11:44:49 -07001738
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001739 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001740
Woody Lin20767a92022-11-29 15:50:24 +08001741 DumpShutdownCheckpoints();
1742
Jayachandran Ca94c7172017-06-10 15:08:12 -07001743 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001744
1745 dump_route_tables();
1746
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001747 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1748 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1749 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001750
Nandana Dutt5c390032019-03-12 10:52:56 +00001751 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysHigh);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001752
Chiachang Wang668ede42021-05-17 17:14:20 +08001753 // 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
Elliott Hughes23ccc622017-02-28 10:14:22 -08001759 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001760
Joe Onoratod38bc3a2023-06-29 15:48:28 -07001761 DumpFile("SYSTEM BUILD-TIME RELEASE FLAGS", "/system/etc/build_flags.json");
1762 DumpFile("SYSTEM_EXT BUILD-TIME RELEASE FLAGS", "/system_ext/etc/build_flags.json");
1763 DumpFile("PRODUCT BUILD-TIME RELEASE FLAGS", "/product/etc/build_flags.json");
1764 DumpFile("VENDOR BUILD-TIME RELEASE FLAGS", "/vendor/etc/build_flags.json");
1765
1766 DumpFile("SYSTEM BUILD-TIME ACONFIG FLAGS (check dumpstate build_config for runtime values)",
1767 "/system/etc/aconfig_flags.textproto");
1768 DumpFile("SYSTEM_EXT BUILD-TIME ACONFIG FLAGS (check dumpstate build_config for runtime"
1769 " values)", "/system_ext/etc/aconfig_flags.textproto");
1770 DumpFile("PRODUCT BUILD-TIME ACONFIG FLAGS (check dumpstate build_config for runtime values)",
1771 "/product/etc/aconfig_flags.textproto");
1772 DumpFile("VENDOR BUILD-TIME ACONFIG FLAGS (check dumpstate build_config for runtime values)",
1773 "/vendor/etc/aconfig_flags.textproto");
1774
Jin Qianf334d662017-10-10 14:41:37 -07001775 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001776
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001777 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001778
Colin Crossf45fa6b2012-03-26 12:38:26 -07001779 /* Binder state is expensive to look at as it uses a lot of memory. */
Hridya Valsaraju920ba712020-02-09 16:27:01 -08001780 std::string binder_logs_dir = access("/dev/binderfs/binder_logs", R_OK) ?
1781 "/sys/kernel/debug/binder" : "/dev/binderfs/binder_logs";
1782
1783 DumpFile("BINDER FAILED TRANSACTION LOG", binder_logs_dir + "/failed_transaction_log");
1784 DumpFile("BINDER TRANSACTION LOG", binder_logs_dir + "/transaction_log");
1785 DumpFile("BINDER TRANSACTIONS", binder_logs_dir + "/transactions");
1786 DumpFile("BINDER STATS", binder_logs_dir + "/stats");
1787 DumpFile("BINDER STATE", binder_logs_dir + "/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001788
Yifan Hongd90cc652020-02-08 16:52:02 -08001789 ds.AddDir(SNAPSHOTCTL_LOG_DIR, false);
1790
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001791 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001792 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_board));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001793 } else {
1794 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
1795 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001796
Steven Moreland7440ddb2016-12-15 16:13:39 -08001797 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001798 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1799 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001800 // su does not exist on user builds, so try running without it.
1801 // This way any implementations of vril-dump that do not require
1802 // root can run on user builds.
1803 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001804 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001805 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001806 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001807 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001808 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001809 }
1810
Felipe Lemed8b94e52016-12-08 10:21:44 -08001811 printf("========================================================\n");
1812 printf("== Android Framework Services\n");
1813 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001814
Nandana Dutt5c390032019-03-12 10:52:56 +00001815 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001816
Jack He91ff2fe2021-02-18 18:23:43 -08001817 /* Dump Bluetooth HCI logs after getting bluetooth_manager dumpsys */
1818 ds.AddDir("/data/misc/bluetooth/logs", true);
1819
Rhed Jaoe017f982020-07-21 17:58:41 +08001820 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001821 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_checkins));
Rhed Jaoe017f982020-07-21 17:58:41 +08001822 } else {
1823 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_CHECKINS_TASK, DumpCheckins);
1824 }
Dianne Hackborn02bea972013-06-26 18:59:09 -07001825
Rhed Jaoc5f7ec32020-12-22 22:11:08 +08001826 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpAppInfos);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001827
Adrian Roos8b397ab2017-04-04 16:35:44 -07001828 printf("========================================================\n");
1829 printf("== Dropbox crashes\n");
1830 printf("========================================================\n");
1831
1832 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1833 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1834
Felipe Lemed8b94e52016-12-08 10:21:44 -08001835 printf("========================================================\n");
1836 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1837 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1838 printf("========================================================\n");
1839 printf("== dumpstate: done (id %d)\n", ds.id_);
1840 printf("========================================================\n");
Bookatz38472142018-09-28 10:20:24 -07001841
1842 printf("========================================================\n");
1843 printf("== Obtaining statsd metadata\n");
1844 printf("========================================================\n");
1845 // This differs from the usual dumpsys stats, which is the stats report data.
1846 RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
Mike Ma5c267872019-08-21 11:31:34 -07001847
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +09001848 // Add linker configuration directory
1849 ds.AddDir(LINKERCONFIG_DIR, true);
1850
Li Li830179f2022-01-04 12:53:29 -08001851 /* Dump frozen cgroupfs */
1852 dump_frozen_cgroupfs();
Li Li2eedd412021-06-30 15:11:53 -07001853
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001854 if (ds.dump_pool_) {
Aaron Huang24d215d2022-04-27 18:51:16 +08001855 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_netstats_report));
1856 } else {
1857 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_NETSTATS_PROTO_TASK,
1858 DumpNetstatsProto);
1859 }
1860
1861 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001862 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_incident_report));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001863 } else {
1864 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_INCIDENT_REPORT_TASK,
1865 DumpIncidentReport);
1866 }
Mike Ma5c267872019-08-21 11:31:34 -07001867
Kean Mariotti306633e2022-09-05 16:30:47 +00001868 if (ds.dump_pool_) {
1869 WaitForTask(std::move(post_process_ui_traces));
1870 } else {
1871 RUN_SLOW_FUNCTION_AND_LOG(POST_PROCESS_UI_TRACES_TASK, MaybePostProcessUiTraces);
1872 }
1873
1874 MaybeAddUiTracesToZip();
1875
Nandana Dutt5c390032019-03-12 10:52:56 +00001876 return Dumpstate::RunStatus::OK;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001877}
1878
Nandana Dutt5c390032019-03-12 10:52:56 +00001879/*
1880 * Dumps state for the default case; drops root after it's no longer necessary.
1881 *
1882 * Returns RunStatus::OK if everything went fine.
1883 * Returns RunStatus::ERROR if there was an error.
1884 * Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport
1885 * with the caller.
1886 */
Jichao Lie89d9c12019-11-21 19:02:51 -08001887Dumpstate::RunStatus Dumpstate::DumpstateDefaultAfterCritical() {
Nandana Duttdb379fa2019-10-09 16:54:41 +01001888 // Capture first logcat early on; useful to take a snapshot before dumpstate logs take over the
1889 // buffer.
1890 DoLogcat();
1891 // Capture timestamp after first logcat to use in next logcat
1892 time_t logcat_ts = time(nullptr);
1893
Nandana Dutt4be45d12018-09-26 15:04:23 +01001894 /* collect stack traces from Dalvik and native processes (needs root) */
Chris Morinbc223142022-02-04 14:17:11 -08001895 std::future<std::string> dump_traces;
Rhed Jao5377d792020-07-16 17:37:39 +08001896 if (dump_pool_) {
1897 RETURN_IF_USER_DENIED_CONSENT();
1898 // One thread is enough since we only need to enqueue DumpTraces here.
1899 dump_pool_->start(/* thread_counts = */1);
1900
1901 // DumpTraces takes long time, post it to the another thread in the
1902 // pool, if pool is available
Chris Morinbc223142022-02-04 14:17:11 -08001903 dump_traces = dump_pool_->enqueueTask(
1904 DUMP_TRACES_TASK, &Dumpstate::DumpTraces, &ds, &dump_traces_path);
Rhed Jao5377d792020-07-16 17:37:39 +08001905 } else {
1906 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_TRACES_TASK, ds.DumpTraces,
1907 &dump_traces_path);
1908 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001909
1910 /* Run some operations that require root. */
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001911 if (!PropertiesHelper::IsDryRun()) {
Chris Morinc2cba7a2022-02-01 17:06:50 -08001912 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX);
1913 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX);
Woody Lin20767a92022-11-29 15:50:24 +08001914 ds.shutdown_checkpoints_ = GetDumpFds(
1915 SHUTDOWN_CHECKPOINTS_DIR, SHUTDOWN_CHECKPOINTS_FILE_PREFIX);
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001916 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001917
1918 ds.AddDir(RECOVERY_DIR, true);
1919 ds.AddDir(RECOVERY_DATA_DIR, true);
1920 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
Kelvin Zhang6eaa0f92022-09-12 09:29:19 -07001921 ds.AddDir(UPDATE_ENGINE_PREF_DIR, true);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001922 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1923 if (!PropertiesHelper::IsUserBuild()) {
1924 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1925 ds.AddDir(PROFILE_DATA_DIR_REF, true);
Calin Juravlef84d3692020-04-28 15:31:12 -07001926 ds.AddZipEntry(ZIP_ROOT_DIR + PACKAGE_DEX_USE_LIST, PACKAGE_DEX_USE_LIST);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001927 }
Jerry Changa1df8a92020-01-02 16:03:39 +08001928 ds.AddDir(PREREBOOT_DATA_DIR, false);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001929 add_mountinfo();
Peter Collingbourne78aa2942023-02-15 14:50:31 -08001930 for (const char* path : {"/proc/cpuinfo", "/proc/meminfo"}) {
1931 ds.AddZipEntry(ZIP_ROOT_DIR + path, path);
1932 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001933 DumpIpTablesAsRoot();
David Andersond9ba4752018-12-11 18:26:59 -08001934 DumpDynamicPartitionInfo();
Yifan Hong3945e1b2019-10-29 12:59:23 -07001935 ds.AddDir(OTA_METADATA_DIR, true);
Jeff Sharkey9df29d52023-02-06 14:26:30 -07001936 if (!PropertiesHelper::IsUserBuild()) {
1937 // Include dropbox entry files inside ZIP, but exclude
1938 // noisy WTF and StrictMode entries
1939 dump_files("", DROPBOX_DIR, skip_wtf_strictmode, _add_file_from_fd);
1940 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001941
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001942 // Capture any IPSec policies in play. No keys are exposed here.
Nandana Dutt4be45d12018-09-26 15:04:23 +01001943 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1944
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001945 // Dump IPsec stats. No keys are exposed here.
1946 DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
1947
Nandana Dutt4be45d12018-09-26 15:04:23 +01001948 // Run ss as root so we can see socket marks.
1949 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1950
1951 // Run iotop as root to show top 100 IO threads
1952 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1953
Erick Reyese68df822019-02-11 14:46:36 -08001954 // Gather shared memory buffer info if the product implements it
Hridya Valsaraju1da80c52021-01-09 22:10:11 -08001955 RunCommand("Dmabuf dump", {"dmabuf_dump"});
1956 RunCommand("Dmabuf per-buffer/per-exporter/per-device stats", {"dmabuf_dump", "-b"});
Erick Reyese68df822019-02-11 14:46:36 -08001957
Minchan Kim22c6a1e2019-09-30 15:58:10 -07001958 DumpFile("PSI cpu", "/proc/pressure/cpu");
1959 DumpFile("PSI memory", "/proc/pressure/memory");
1960 DumpFile("PSI io", "/proc/pressure/io");
1961
Mårten Kongstad60195a72022-09-20 14:14:20 +02001962 RunCommand("SDK EXTENSIONS", {SDK_EXT_INFO, "--dump"},
1963 CommandOptions::WithTimeout(10).Always().DropRoot().Build());
1964
Rhed Jao5377d792020-07-16 17:37:39 +08001965 if (dump_pool_) {
1966 RETURN_IF_USER_DENIED_CONSENT();
Chris Morinbc223142022-02-04 14:17:11 -08001967 WaitForTask(std::move(dump_traces));
Rhed Jao5377d792020-07-16 17:37:39 +08001968
Chris Morinbc223142022-02-04 14:17:11 -08001969 // Current running thread in the pool is the root user also. Delete
1970 // the pool and make a new one later to ensure none of threads in the pool are root.
1971 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao5377d792020-07-16 17:37:39 +08001972 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001973 if (!DropRootUser()) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001974 return Dumpstate::RunStatus::ERROR;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001975 }
1976
Nandana Dutt5c390032019-03-12 10:52:56 +00001977 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttdb379fa2019-10-09 16:54:41 +01001978 Dumpstate::RunStatus status = dumpstate();
1979 // Capture logcat since the last time we did it.
1980 DoSystemLogcat(logcat_ts);
1981 return status;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001982}
1983
Rhed Jaob5685b32020-08-14 17:19:17 +08001984// Common states for telephony and wifi which are needed to be collected before
1985// dumpstate drop the root user.
1986static void DumpstateRadioAsRoot() {
1987 DumpIpTablesAsRoot();
1988 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1989}
1990
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001991// This method collects common dumpsys for telephony and wifi. Typically, wifi
1992// reports are fine to include all information, but telephony reports on user
1993// builds need to strip some content (see DumpstateTelephonyOnly).
1994static void DumpstateRadioCommon(bool include_sensitive_info = true) {
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001995 // We need to be picky about some stuff for telephony reports on user builds.
1996 if (!include_sensitive_info) {
1997 // Only dump the radio log buffer (other buffers and dumps contain too much unrelated info).
1998 DoRadioLogcat();
1999 } else {
Rhed Jaob5685b32020-08-14 17:19:17 +08002000 // DumpHals takes long time, post it to the another thread in the pool,
2001 // if pool is available.
Chris Morinbc223142022-02-04 14:17:11 -08002002 std::future<std::string> dump_hals;
Rhed Jaob5685b32020-08-14 17:19:17 +08002003 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002004 dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
Rhed Jaob5685b32020-08-14 17:19:17 +08002005 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002006 // Contains various system properties and process startup info.
2007 do_dmesg();
2008 // Logs other than the radio buffer may contain package/component names and potential PII.
2009 DoLogcat();
2010 // Too broad for connectivity problems.
2011 DoKmsg();
Rhed Jaob5685b32020-08-14 17:19:17 +08002012 // DumpHals contains unrelated hardware info (camera, NFC, biometrics, ...).
2013 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002014 WaitForTask(std::move(dump_hals));
Rhed Jaob5685b32020-08-14 17:19:17 +08002015 } else {
2016 RUN_SLOW_FUNCTION_AND_LOG(DUMP_HALS_TASK, DumpHals);
2017 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002018 }
2019
Jayachandran Ca94c7172017-06-10 15:08:12 -07002020 DumpPacketStats();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002021 DumpIpAddrAndRules();
2022 dump_route_tables();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002023 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
2024 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08002025}
2026
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002027// We use "telephony" here for legacy reasons, though this now really means "connectivity" (cellular
2028// + wifi + networking). This method collects dumpsys for connectivity debugging only. General rules
2029// for what can be included on user builds: all reported information MUST directly relate to
2030// connectivity debugging or customer support and MUST NOT contain unrelated personally identifiable
2031// information. This information MUST NOT identify user-installed packages (UIDs are OK, package
2032// names are not), and MUST NOT contain logs of user application traffic.
2033// TODO(b/148168577) rename this and other related fields/methods to "connectivity" instead.
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08002034static void DumpstateTelephonyOnly(const std::string& calling_package) {
mukesh agrawal253dad42018-01-23 21:59:59 -08002035 DurationReporter duration_reporter("DUMPSTATE");
Jichao Lie89d9c12019-11-21 19:02:51 -08002036
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002037 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
mukesh agrawal253dad42018-01-23 21:59:59 -08002038
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002039 const bool include_sensitive_info = !PropertiesHelper::IsUserBuild();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002040
Rhed Jaob5685b32020-08-14 17:19:17 +08002041 DumpstateRadioAsRoot();
2042 if (!DropRootUser()) {
2043 return;
2044 }
2045
2046 // Starts thread pool after the root user is dropped, and two additional threads
2047 // are created for DumpHals in the DumpstateRadioCommon and DumpstateBoard.
Chris Morinbc223142022-02-04 14:17:11 -08002048 std::future<std::string> dump_board;
Rhed Jaob5685b32020-08-14 17:19:17 +08002049 if (ds.dump_pool_) {
2050 ds.dump_pool_->start(/*thread_counts =*/2);
2051
2052 // DumpstateBoard takes long time, post it to the another thread in the pool,
2053 // if pool is available.
Chris Morinbc223142022-02-04 14:17:11 -08002054 dump_board = ds.dump_pool_->enqueueTaskWithFd(
2055 DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
Rhed Jaob5685b32020-08-14 17:19:17 +08002056 }
2057
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002058 DumpstateRadioCommon(include_sensitive_info);
2059
2060 if (include_sensitive_info) {
2061 // Contains too much unrelated PII, and given the unstructured nature of sysprops, we can't
2062 // really cherrypick all of the connectivity-related ones. Apps generally have no business
2063 // reading these anyway, and there should be APIs to supply the info in a more app-friendly
2064 // way.
2065 RunCommand("SYSTEM PROPERTIES", {"getprop"});
2066 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002067
2068 printf("========================================================\n");
2069 printf("== Android Framework Services\n");
2070 printf("========================================================\n");
2071
Vishnu Nair652cc802017-11-30 15:18:30 -08002072 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2073 SEC_TO_MSEC(10));
Hunter Knepshield31cbae12021-05-11 16:23:24 -07002074 RunDumpsys("DUMPSYS", {"vcn_management"}, CommandOptions::WithTimeout(90).Build(),
2075 SEC_TO_MSEC(10));
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08002076 if (include_sensitive_info) {
2077 // Carrier apps' services will be dumped below in dumpsys activity service all-non-platform.
2078 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
2079 SEC_TO_MSEC(10));
2080 } else {
2081 // If the caller is a carrier app and has a carrier service, dump it here since we aren't
2082 // running dumpsys activity service all-non-platform below. Due to the increased output, we
2083 // give a higher timeout as well.
2084 RunDumpsys("DUMPSYS", {"carrier_config", "--requesting-package", calling_package},
2085 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(30));
2086 }
2087 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002088 RunDumpsys("DUMPSYS", {"netpolicy"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2089 RunDumpsys("DUMPSYS", {"network_management"}, CommandOptions::WithTimeout(90).Build(),
Sooraj Sasindrane8d98912018-04-20 11:31:55 -07002090 SEC_TO_MSEC(10));
Hunter Knepshield0fe51b12020-03-05 16:58:20 -08002091 RunDumpsys("DUMPSYS", {"telephony.registry"}, CommandOptions::WithTimeout(90).Build(),
2092 SEC_TO_MSEC(10));
Jack Yu773cc032023-03-16 22:43:39 -07002093 RunDumpsys("DUMPSYS", {"isub"}, CommandOptions::WithTimeout(90).Build(),
2094 SEC_TO_MSEC(10));
Grant Menke56698972023-02-24 13:11:07 -08002095 RunDumpsys("DUMPSYS", {"telecom"}, CommandOptions::WithTimeout(90).Build(),
2096 SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002097 if (include_sensitive_info) {
2098 // Contains raw IP addresses, omit from reports on user builds.
2099 RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2100 // Contains raw destination IP/MAC addresses, omit from reports on user builds.
2101 RunDumpsys("DUMPSYS", {"connmetrics"}, CommandOptions::WithTimeout(90).Build(),
2102 SEC_TO_MSEC(10));
2103 // Contains package/component names, omit from reports on user builds.
2104 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
2105 SEC_TO_MSEC(10));
2106 // Contains package names, but should be relatively simple to remove them (also contains
2107 // UIDs already), omit from reports on user builds.
2108 RunDumpsys("BATTERYSTATS", {"deviceidle"}, CommandOptions::WithTimeout(90).Build(),
2109 SEC_TO_MSEC(10));
2110 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002111
2112 printf("========================================================\n");
2113 printf("== Running Application Services\n");
2114 printf("========================================================\n");
2115
2116 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
2117
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002118 if (include_sensitive_info) {
2119 printf("========================================================\n");
2120 printf("== Running Application Services (non-platform)\n");
2121 printf("========================================================\n");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002122
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002123 // Contains package/component names and potential PII, omit from reports on user builds.
2124 // To get dumps of the active CarrierService(s) on user builds, we supply an argument to the
2125 // carrier_config dumpsys instead.
2126 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
2127 DUMPSYS_COMPONENTS_OPTIONS);
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002128
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002129 printf("========================================================\n");
2130 printf("== Checkins\n");
2131 printf("========================================================\n");
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002132
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002133 // Contains package/component names, omit from reports on user builds.
2134 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
2135 }
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002136
2137 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07002138 printf("== dumpstate: done (id %d)\n", ds.id_);
2139 printf("========================================================\n");
Rhed Jaob5685b32020-08-14 17:19:17 +08002140
2141 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002142 WaitForTask(std::move(dump_board));
Rhed Jaob5685b32020-08-14 17:19:17 +08002143 } else {
2144 RUN_SLOW_FUNCTION_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
2145 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002146}
2147
mukesh agrawal253dad42018-01-23 21:59:59 -08002148// This method collects dumpsys for wifi debugging only
2149static void DumpstateWifiOnly() {
2150 DurationReporter duration_reporter("DUMPSTATE");
2151
Rhed Jaob5685b32020-08-14 17:19:17 +08002152 DumpstateRadioAsRoot();
2153 if (!DropRootUser()) {
2154 return;
2155 }
2156
2157 // Starts thread pool after the root user is dropped. Only one additional
2158 // thread is needed for DumpHals in the DumpstateRadioCommon.
2159 if (ds.dump_pool_) {
2160 ds.dump_pool_->start(/*thread_counts =*/1);
2161 }
2162
mukesh agrawal253dad42018-01-23 21:59:59 -08002163 DumpstateRadioCommon();
2164
2165 printf("========================================================\n");
2166 printf("== Android Framework Services\n");
2167 printf("========================================================\n");
2168
2169 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2170 SEC_TO_MSEC(10));
2171 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
2172 SEC_TO_MSEC(10));
2173
2174 printf("========================================================\n");
2175 printf("== dumpstate: done (id %d)\n", ds.id_);
2176 printf("========================================================\n");
2177}
2178
Elis Elliott8e401ad2023-08-08 11:18:59 +00002179// Collects a lightweight dumpstate to be used for debugging onboarding related flows.
2180static void DumpstateOnboardingOnly() {
2181 ds.AddDir(LOGPERSIST_DATA_DIR, false);
2182}
2183
Nandana Duttcf419a72019-03-14 10:40:17 +00002184Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
Gavin Corkery789d7a52021-02-24 23:52:35 +00002185 const std::string temp_file_pattern = ds.bugreport_internal_dir_ + "/dumptrace_XXXXXX";
Nandana Duttfaafd522019-03-11 09:23:09 +00002186 const size_t buf_size = temp_file_pattern.length() + 1;
2187 std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
2188 memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
2189
2190 // Create a new, empty file to receive all trace dumps.
2191 //
2192 // TODO: This can be simplified once we remove support for the old style
2193 // dumps. We can have a file descriptor passed in to dump_traces instead
2194 // of creating a file, closing it and then reopening it again.
2195 android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
2196 if (fd < 0) {
2197 MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002198 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002199 }
2200
2201 // Nobody should have access to this temporary file except dumpstate, but we
2202 // temporarily grant 'read' to 'others' here because this file is created
2203 // when tombstoned is still running as root, but dumped after dropping. This
2204 // can go away once support for old style dumping has.
2205 const int chmod_ret = fchmod(fd, 0666);
2206 if (chmod_ret < 0) {
2207 MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002208 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002209 }
2210
2211 std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
2212 if (proc.get() == nullptr) {
2213 MYLOGE("opendir /proc failed: %s\n", strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002214 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002215 }
2216
2217 // Number of times process dumping has timed out. If we encounter too many
2218 // failures, we'll give up.
2219 int timeout_failures = 0;
2220 bool dalvik_found = false;
2221
Jayant Chowdharya0a8eb22022-05-20 03:30:09 +00002222 const std::set<int> hal_pids = get_interesting_pids();
Nandana Duttfaafd522019-03-11 09:23:09 +00002223
2224 struct dirent* d;
2225 while ((d = readdir(proc.get()))) {
Nandana Duttcf419a72019-03-14 10:40:17 +00002226 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttfaafd522019-03-11 09:23:09 +00002227 int pid = atoi(d->d_name);
2228 if (pid <= 0) {
2229 continue;
2230 }
2231
Kevin Jeond0f8a982023-04-07 14:27:11 -04002232 // Skip cached processes.
2233 if (IsCached(pid)) {
2234 // For consistency, the header and footer to this message match those
2235 // dumped by debuggerd in the success case.
2236 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
2237 dprintf(fd, "Dump skipped for cached process.\n");
2238 dprintf(fd, "---- end %d ----", pid);
2239 continue;
2240 }
2241
Nandana Duttfaafd522019-03-11 09:23:09 +00002242 const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
2243 std::string exe;
2244 if (!android::base::Readlink(link_name, &exe)) {
2245 continue;
2246 }
2247
2248 bool is_java_process;
2249 if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
2250 // Don't bother dumping backtraces for the zygote.
2251 if (IsZygote(pid)) {
2252 continue;
2253 }
2254
2255 dalvik_found = true;
2256 is_java_process = true;
2257 } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
2258 is_java_process = false;
2259 } else {
2260 // Probably a native process we don't care about, continue.
2261 continue;
2262 }
2263
2264 // If 3 backtrace dumps fail in a row, consider debuggerd dead.
2265 if (timeout_failures == 3) {
2266 dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
2267 break;
2268 }
2269
2270 const uint64_t start = Nanotime();
2271 const int ret = dump_backtrace_to_file_timeout(
Kevin Jeonb8a39362023-04-04 15:00:34 -04002272 pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace, 3, fd);
Nandana Duttfaafd522019-03-11 09:23:09 +00002273
2274 if (ret == -1) {
2275 // For consistency, the header and footer to this message match those
2276 // dumped by debuggerd in the success case.
2277 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
2278 dprintf(fd, "Dump failed, likely due to a timeout.\n");
2279 dprintf(fd, "---- end %d ----", pid);
2280 timeout_failures++;
2281 continue;
2282 }
2283
2284 // We've successfully dumped stack traces, reset the failure count
2285 // and write a summary of the elapsed time to the file and continue with the
2286 // next process.
2287 timeout_failures = 0;
2288
2289 dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
2290 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
2291 }
2292
2293 if (!dalvik_found) {
2294 MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
2295 }
2296
Nandana Duttcf419a72019-03-14 10:40:17 +00002297 *path = file_name_buf.release();
2298 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002299}
2300
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002301static dumpstate_hal_hidl::DumpstateMode GetDumpstateHalModeHidl(
2302 const Dumpstate::BugreportMode bugreport_mode) {
2303 switch (bugreport_mode) {
2304 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2305 return dumpstate_hal_hidl::DumpstateMode::FULL;
2306 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2307 return dumpstate_hal_hidl::DumpstateMode::INTERACTIVE;
2308 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2309 return dumpstate_hal_hidl::DumpstateMode::REMOTE;
2310 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2311 return dumpstate_hal_hidl::DumpstateMode::WEAR;
2312 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2313 return dumpstate_hal_hidl::DumpstateMode::CONNECTIVITY;
2314 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2315 return dumpstate_hal_hidl::DumpstateMode::WIFI;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002316 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002317 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2318 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2319 }
2320 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2321}
2322
2323static dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode GetDumpstateHalModeAidl(
2324 const Dumpstate::BugreportMode bugreport_mode) {
2325 switch (bugreport_mode) {
2326 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2327 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::FULL;
2328 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2329 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::INTERACTIVE;
2330 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2331 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::REMOTE;
2332 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2333 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WEAR;
2334 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2335 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::CONNECTIVITY;
2336 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2337 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WIFI;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002338 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002339 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2340 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2341 }
2342 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2343}
2344
2345static void DoDumpstateBoardHidl(
2346 const sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_1_0,
2347 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2348 const Dumpstate::BugreportMode bugreport_mode,
2349 const size_t timeout_sec) {
2350
2351 using ScopedNativeHandle =
2352 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
2353 ScopedNativeHandle handle(native_handle_create(static_cast<int>(dumpstate_fds.size()), 0),
2354 [](native_handle_t* handle) {
2355 // we don't close file handle's here
2356 // via native_handle_close(handle)
2357 // instead we let dumpstate_fds close the file handles when
2358 // dumpstate_fds gets destroyed
2359 native_handle_delete(handle);
2360 });
2361 if (handle == nullptr) {
2362 MYLOGE("Could not create native_handle for dumpstate HAL\n");
2363 return;
2364 }
2365
2366 for (size_t i = 0; i < dumpstate_fds.size(); i++) {
2367 handle.get()->data[i] = dumpstate_fds[i].get();
2368 }
2369
2370 // Prefer version 1.1 if available. New devices launching with R are no longer allowed to
2371 // implement just 1.0.
2372 const char* descriptor_to_kill;
2373 using DumpstateBoardTask = std::packaged_task<bool()>;
2374 DumpstateBoardTask dumpstate_board_task;
2375 sp<dumpstate_hal_hidl::IDumpstateDevice> dumpstate_hal(
2376 dumpstate_hal_hidl::IDumpstateDevice::castFrom(dumpstate_hal_1_0));
2377 if (dumpstate_hal != nullptr) {
2378 MYLOGI("Using IDumpstateDevice v1.1 HIDL HAL");
2379
2380 dumpstate_hal_hidl::DumpstateMode dumpstate_hal_mode =
2381 GetDumpstateHalModeHidl(bugreport_mode);
2382
2383 descriptor_to_kill = dumpstate_hal_hidl::IDumpstateDevice::descriptor;
2384 dumpstate_board_task =
2385 DumpstateBoardTask([timeout_sec, dumpstate_hal_mode, dumpstate_hal, &handle]() -> bool {
2386 ::android::hardware::Return<dumpstate_hal_hidl::DumpstateStatus> status =
2387 dumpstate_hal->dumpstateBoard_1_1(handle.get(), dumpstate_hal_mode,
2388 SEC_TO_MSEC(timeout_sec));
2389 if (!status.isOk()) {
2390 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2391 return false;
2392 } else if (status != dumpstate_hal_hidl::DumpstateStatus::OK) {
2393 MYLOGE("dumpstateBoard failed with DumpstateStatus::%s\n",
2394 dumpstate_hal_hidl::toString(status).c_str());
2395 return false;
2396 }
2397 return true;
2398 });
2399 } else {
2400 MYLOGI("Using IDumpstateDevice v1.0 HIDL HAL");
2401
2402 descriptor_to_kill = dumpstate_hal_hidl_1_0::IDumpstateDevice::descriptor;
2403 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal_1_0, &handle]() -> bool {
2404 ::android::hardware::Return<void> status =
2405 dumpstate_hal_1_0->dumpstateBoard(handle.get());
2406 if (!status.isOk()) {
2407 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2408 return false;
2409 }
2410 return true;
2411 });
2412 }
2413 auto result = dumpstate_board_task.get_future();
2414 std::thread(std::move(dumpstate_board_task)).detach();
2415
2416 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2417 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2418 if (!android::base::SetProperty(
2419 "ctl.interface_restart",
2420 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2421 MYLOGE("Couldn't restart dumpstate HAL\n");
2422 }
2423 }
2424 // Wait some time for init to kill dumpstate vendor HAL
2425 constexpr size_t killing_timeout_sec = 10;
2426 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2427 MYLOGE(
2428 "killing dumpstateBoard timed out after %zus, continue and "
2429 "there might be racing in content\n",
2430 killing_timeout_sec);
2431 }
2432}
2433
2434static void DoDumpstateBoardAidl(
2435 const std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal,
2436 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2437 const Dumpstate::BugreportMode bugreport_mode, const size_t timeout_sec) {
2438 MYLOGI("Using IDumpstateDevice AIDL HAL");
2439
2440 const char* descriptor_to_kill;
2441 using DumpstateBoardTask = std::packaged_task<bool()>;
2442 DumpstateBoardTask dumpstate_board_task;
2443 dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode dumpstate_hal_mode =
2444 GetDumpstateHalModeAidl(bugreport_mode);
2445
2446 descriptor_to_kill = dumpstate_hal_aidl::IDumpstateDevice::descriptor;
2447 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal, &dumpstate_fds, dumpstate_hal_mode,
2448 timeout_sec]() -> bool {
2449 auto status = dumpstate_hal->dumpstateBoard(dumpstate_fds, dumpstate_hal_mode, timeout_sec);
2450
2451 if (!status.isOk()) {
2452 MYLOGE("dumpstateBoard failed: %s\n", status.getDescription().c_str());
2453 return false;
2454 }
2455 return true;
2456 });
2457 auto result = dumpstate_board_task.get_future();
2458 std::thread(std::move(dumpstate_board_task)).detach();
2459
2460 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2461 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2462 if (!android::base::SetProperty(
2463 "ctl.interface_restart",
2464 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2465 MYLOGE("Couldn't restart dumpstate HAL\n");
2466 }
2467 }
2468 // Wait some time for init to kill dumpstate vendor HAL
2469 constexpr size_t killing_timeout_sec = 10;
2470 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2471 MYLOGE(
2472 "killing dumpstateBoard timed out after %zus, continue and "
2473 "there might be racing in content\n",
2474 killing_timeout_sec);
2475 }
2476}
2477
2478static std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> GetDumpstateBoardAidlService() {
2479 const std::string aidl_instance_name =
2480 std::string(dumpstate_hal_aidl::IDumpstateDevice::descriptor) + "/default";
2481
2482 if (!AServiceManager_isDeclared(aidl_instance_name.c_str())) {
2483 return nullptr;
2484 }
2485
2486 ndk::SpAIBinder dumpstateBinder(AServiceManager_waitForService(aidl_instance_name.c_str()));
2487
2488 return dumpstate_hal_aidl::IDumpstateDevice::fromBinder(dumpstateBinder);
2489}
2490
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002491void Dumpstate::DumpstateBoard(int out_fd) {
2492 dprintf(out_fd, "========================================================\n");
2493 dprintf(out_fd, "== Board\n");
2494 dprintf(out_fd, "========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08002495
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002496 /*
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002497 * mount debugfs for non-user builds with ro.product.debugfs_restrictions.enabled
Hridya Valsaraju51101602021-04-02 14:32:46 -07002498 * set to true and unmount it after invoking dumpstateBoard_* methods.
2499 * This is to enable debug builds to not have debugfs mounted during runtime.
2500 * It will also ensure that debugfs is only accessed by the dumpstate HAL.
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002501 */
Hridya Valsaraju51101602021-04-02 14:32:46 -07002502 auto mount_debugfs =
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002503 android::base::GetBoolProperty("ro.product.debugfs_restrictions.enabled", false);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002504 if (mount_debugfs) {
2505 RunCommand("mount debugfs", {"mount", "-t", "debugfs", "debugfs", "/sys/kernel/debug"},
2506 AS_ROOT_20);
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002507 RunCommand("chmod debugfs", {"chmod", "0755", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002508 }
2509
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002510 std::vector<std::string> paths;
2511 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07002512 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002513 paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
2514 kDumpstateBoardFiles[i].c_str()));
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002515 remover.emplace_back(android::base::make_scope_guard(
2516 std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002517 }
Jie Song9fbfad02017-06-20 16:29:42 -07002518
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002519 // get dumpstate HAL AIDL implementation
2520 std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal_handle_aidl(
2521 GetDumpstateBoardAidlService());
2522 if (dumpstate_hal_handle_aidl == nullptr) {
2523 MYLOGI("No IDumpstateDevice AIDL implementation\n");
2524 }
2525
2526 // get dumpstate HAL HIDL implementation, only if AIDL HAL implementation not found
2527 sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_handle_hidl_1_0 = nullptr;
2528 if (dumpstate_hal_handle_aidl == nullptr) {
2529 dumpstate_hal_handle_hidl_1_0 = dumpstate_hal_hidl_1_0::IDumpstateDevice::getService();
2530 if (dumpstate_hal_handle_hidl_1_0 == nullptr) {
2531 MYLOGI("No IDumpstateDevice HIDL implementation\n");
2532 }
2533 }
2534
2535 // if neither HIDL nor AIDL implementation found, then return
2536 if (dumpstate_hal_handle_hidl_1_0 == nullptr && dumpstate_hal_handle_aidl == nullptr) {
2537 MYLOGE("Could not find IDumpstateDevice implementation\n");
Wei Wang587eac92018-04-05 12:17:20 -07002538 return;
2539 }
2540
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002541 // this is used to hold the file descriptors and when this variable goes out of scope
2542 // the file descriptors are closed
2543 std::vector<::ndk::ScopedFileDescriptor> dumpstate_fds;
Wei Wang587eac92018-04-05 12:17:20 -07002544
Nandana Dutt5c390032019-03-12 10:52:56 +00002545 // TODO(128270426): Check for consent in between?
Wei Wang587eac92018-04-05 12:17:20 -07002546 for (size_t i = 0; i < paths.size(); i++) {
2547 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
2548
2549 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
2550 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
2551 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
2552 if (fd < 0) {
2553 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
2554 return;
2555 }
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002556
2557 dumpstate_fds.emplace_back(fd.release());
2558 // we call fd.release() here to make sure "fd" does not get closed
2559 // after "fd" goes out of scope after this block.
2560 // "fd" will be closed when "dumpstate_fds" goes out of scope
2561 // i.e. when we exit this function
Wei Wang587eac92018-04-05 12:17:20 -07002562 }
2563
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002564 // Given that bugreport is required to diagnose failures, it's better to set an arbitrary amount
2565 // of timeout for IDumpstateDevice than to block the rest of bugreport. In the timeout case, we
2566 // will kill the HAL and grab whatever it dumped in time.
Michael Eastwood8523ea02022-03-10 16:33:08 -08002567 constexpr size_t timeout_sec = 45;
Wei Wang587eac92018-04-05 12:17:20 -07002568
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002569 if (dumpstate_hal_handle_aidl != nullptr) {
2570 DoDumpstateBoardAidl(dumpstate_hal_handle_aidl, dumpstate_fds, options_->bugreport_mode,
2571 timeout_sec);
2572 } else if (dumpstate_hal_handle_hidl_1_0 != nullptr) {
2573 // run HIDL HAL only if AIDL HAL not found
2574 DoDumpstateBoardHidl(dumpstate_hal_handle_hidl_1_0, dumpstate_fds, options_->bugreport_mode,
2575 timeout_sec);
Wei Wang587eac92018-04-05 12:17:20 -07002576 }
2577
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002578 if (mount_debugfs) {
Hridya Valsaraju51101602021-04-02 14:32:46 -07002579 auto keep_debugfs_mounted =
2580 android::base::GetProperty("persist.dbg.keep_debugfs_mounted", "");
2581 if (keep_debugfs_mounted.empty())
2582 RunCommand("unmount debugfs", {"umount", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002583 }
2584
Wei Wang587eac92018-04-05 12:17:20 -07002585 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
2586 for (size_t i = 0; i < paths.size(); i++) {
2587 struct stat s;
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002588 if (fstat(dumpstate_fds[i].get(), &s) == -1) {
2589 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(), strerror(errno));
Wei Wang587eac92018-04-05 12:17:20 -07002590 file_sizes[i] = -1;
2591 continue;
2592 }
2593 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002594 }
2595
2596 for (size_t i = 0; i < paths.size(); i++) {
2597 if (file_sizes[i] == -1) {
2598 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002599 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002600 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07002601 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002602 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002603 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002604 remover[i].Disable();
2605 EnqueueAddZipEntryAndCleanupIfNeeded(kDumpstateBoardFiles[i], paths[i]);
2606 dprintf(out_fd, "*** See %s entry ***\n", kDumpstateBoardFiles[i].c_str());
Jie Song9fbfad02017-06-20 16:29:42 -07002607 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08002608}
2609
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002610static void ShowUsage() {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002611 fprintf(stderr,
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002612 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o directory] [-p] "
2613 "[-s] [-S] [-q] [-P] [-R] [-L] [-V version]\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002614 " -h: display this help message\n"
2615 " -b: play sound file instead of vibrate, at beginning of job\n"
2616 " -e: play sound file instead of vibrate, at end of job\n"
mhasank2d75c442020-06-11 15:05:25 -07002617 " -o: write to custom directory (only in limited mode)\n"
Abhijeet Kaurbb55a3b2019-06-13 18:07:25 +01002618 " -p: capture screenshot to filename.png\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002619 " -s: write zipped file to control socket (for init)\n"
2620 " -S: write file location to control socket (for init)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002621 " -q: disable vibrate\n"
Abhijeet Kaure370d682019-10-01 16:49:30 +01002622 " -P: send broadcast when started and do progress updates\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002623 " -R: take bugreport in remote mode (shouldn't be used with -P)\n"
Nandana Dutt235864b2019-01-22 12:10:16 +00002624 " -w: start binder service and make it wait for a call to startBugreport\n"
mhasankd451a472020-05-26 18:02:39 -07002625 " -L: output limited information that is safe for submission in feedback reports\n"
Felipe Lemed071c682016-10-20 16:48:00 -07002626 " -v: prints the dumpstate header and exit\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002627}
2628
Wei Liuf87959e2016-08-26 14:51:42 -07002629static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07002630 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07002631}
2632
Felipe Leme1d486fe2016-10-14 18:06:47 -07002633bool Dumpstate::FinishZipFile() {
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002634 // Runs all enqueued adding zip entry and cleanup tasks before finishing the zip file.
2635 if (zip_entry_tasks_) {
2636 zip_entry_tasks_->run(/* do_cancel = */false);
2637 }
2638
Felipe Leme9a523ae2016-10-20 15:10:33 -07002639 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07002640 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07002641 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002642 // Final timestamp
2643 char date[80];
2644 time_t the_real_now_please_stand_up = time(nullptr);
2645 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002646 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002647 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002648
Felipe Leme9a523ae2016-10-20 15:10:33 -07002649 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002650 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08002651 return false;
2652 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07002653 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002654 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08002655 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08002656 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08002657
Felipe Leme0f3fb202016-06-10 17:10:53 -07002658 // Add log file (which contains stderr output) to zip...
2659 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002660 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07002661 MYLOGE("Failed to add dumpstate log to .zip file\n");
2662 return false;
2663 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002664 // TODO: Should truncate the existing file.
2665 // ... and re-open it for further logging.
Nandana Dutta344cb62019-02-22 15:12:35 +00002666 if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
2667 return false;
2668 }
Felipe Leme0f3fb202016-06-10 17:10:53 -07002669 fprintf(stderr, "\n");
2670
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002671 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07002672 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002673 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002674 return false;
2675 }
2676
Felipe Leme1d486fe2016-10-14 18:06:47 -07002677 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
2678 ds.zip_file.reset(nullptr);
2679
Felipe Lemee9d2c542016-11-15 11:48:26 -08002680 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002681 android::os::UnlinkAndLogOnError(tmp_path_);
Felipe Lemec4eee562016-04-21 15:42:55 -07002682
Felipe Leme1e9edc62015-12-21 16:02:13 -08002683 return true;
2684}
Felipe Leme6e01fa62015-11-11 19:35:14 -08002685
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00002686static void SendBroadcast(const std::string& action,
2687 const std::vector<std::string>& args,
2688 int32_t user_id) {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002689 // clang-format off
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00002690 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user",
2691 std::to_string(user_id), "--receiver-foreground",
2692 "--receiver-include-background", "-a", action};
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002693 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08002694
2695 am.insert(am.end(), args.begin(), args.end());
2696
Felipe Leme8d2410e2017-02-08 09:46:08 -08002697 RunCommand("", am,
2698 CommandOptions::WithTimeout(20)
2699 .Log("Sending broadcast: '%s'\n")
2700 .Always()
2701 .DropRoot()
2702 .RedirectStderr()
2703 .Build());
2704}
2705
Felipe Leme35b8cf12017-02-10 15:47:29 -08002706static void Vibrate(int duration_ms) {
2707 // clang-format off
Lais Andrade51156962021-02-22 19:21:35 +00002708 std::vector<std::string> args = {"cmd", "vibrator_manager", "synced", "-f", "-d", "dumpstate",
2709 "oneshot", std::to_string(duration_ms)};
2710 RunCommand("", args,
Felipe Leme35b8cf12017-02-10 15:47:29 -08002711 CommandOptions::WithTimeout(10)
2712 .Log("Vibrate: '%s'\n")
2713 .Always()
2714 .Build());
2715 // clang-format on
2716}
2717
Nandana Dutt979388e2018-11-30 16:48:55 +00002718static void MaybeResolveSymlink(std::string* path) {
2719 std::string resolved_path;
2720 if (android::base::Readlink(*path, &resolved_path)) {
2721 *path = resolved_path;
2722 }
2723}
2724
Nandana Dutt4be45d12018-09-26 15:04:23 +01002725/*
2726 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002727 * and adds the version file. Return false if zip_file could not be open to write.
Nandana Dutt4be45d12018-09-26 15:04:23 +01002728 */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002729static bool PrepareToWriteToFile() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002730 MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2731
Nandana Dutt4be45d12018-09-26 15:04:23 +01002732 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2733 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002734 ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002735 char date[80];
2736 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2737 ds.name_ = date;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002738
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002739 if (ds.options_->telephony_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002740 ds.base_name_ += "-telephony";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002741 } else if (ds.options_->wifi_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002742 ds.base_name_ += "-wifi";
2743 }
2744
Paul Chang0d2aad72020-02-13 20:04:03 +08002745 if (ds.options_->do_screenshot) {
Nandana Dutt9d17b942020-03-26 10:02:59 +00002746 ds.screenshot_path_ = ds.GetPath(ds.CalledByApi() ? "-png.tmp" : ".png");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002747 }
2748 ds.tmp_path_ = ds.GetPath(".tmp");
2749 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2750
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01002751 std::string destination = ds.CalledByApi()
Nandana Dutt54dbd672019-01-11 12:58:05 +00002752 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
Nandana Dutt9a76d202019-01-21 15:56:48 +00002753 : ds.bugreport_internal_dir_.c_str();
Nandana Dutt4be45d12018-09-26 15:04:23 +01002754 MYLOGD(
Nandana Dutt235c6672019-11-14 15:22:32 +00002755 "Bugreport dir: [%s] "
2756 "Base name: [%s] "
2757 "Suffix: [%s] "
2758 "Log path: [%s] "
2759 "Temporary path: [%s] "
2760 "Screenshot path: [%s]\n",
Nandana Dutt9a76d202019-01-21 15:56:48 +00002761 destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2762 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002763
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002764 ds.path_ = ds.GetPath(ds.CalledByApi() ? "-zip.tmp" : ".zip");
2765 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2766 create_parent_dirs(ds.path_.c_str());
2767 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2768 if (ds.zip_file == nullptr) {
2769 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2770 return false;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002771 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002772 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2773 ds.AddTextZipEntry("version.txt", ds.version_);
2774 return true;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002775}
2776
2777/*
Abhijeet Kaure370d682019-10-01 16:49:30 +01002778 * Finalizes writing to the file by zipping the tmp file to the final location,
Nandana Dutt4be45d12018-09-26 15:04:23 +01002779 * printing zipped file status, etc.
2780 */
2781static void FinalizeFile() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002782 bool do_text_file = !ds.FinishZipFile();
2783 if (do_text_file) {
2784 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002785 }
mhasank2d75c442020-06-11 15:05:25 -07002786
2787 std::string final_path = ds.path_;
2788 if (ds.options_->OutputToCustomFile()) {
mhasank3a4cfb42020-06-15 18:06:43 -07002789 final_path = ds.GetPath(ds.options_->out_dir, ".zip");
mhasank2d75c442020-06-11 15:05:25 -07002790 android::os::CopyFileToFile(ds.path_, final_path);
2791 }
2792
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002793 if (ds.options_->stream_to_socket) {
2794 android::os::CopyFileToFd(ds.path_, ds.control_socket_fd_);
2795 } else if (ds.options_->progress_updates_to_socket) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002796 if (do_text_file) {
2797 dprintf(ds.control_socket_fd_,
2798 "FAIL:could not create zip file, check %s "
2799 "for more details\n",
2800 ds.log_path_.c_str());
2801 } else {
mhasank2d75c442020-06-11 15:05:25 -07002802 dprintf(ds.control_socket_fd_, "OK:%s\n", final_path.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002803 }
2804 }
2805}
2806
Nandana Dutt4be45d12018-09-26 15:04:23 +01002807
Nandana Dutt58d72e22018-11-16 10:30:48 +00002808static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2809 switch (mode) {
2810 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2811 return "BUGREPORT_FULL";
2812 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2813 return "BUGREPORT_INTERACTIVE";
2814 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2815 return "BUGREPORT_REMOTE";
2816 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2817 return "BUGREPORT_WEAR";
2818 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2819 return "BUGREPORT_TELEPHONY";
2820 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2821 return "BUGREPORT_WIFI";
Elis Elliott8e401ad2023-08-08 11:18:59 +00002822 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
2823 return "BUGREPORT_ONBOARDING";
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002824 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2825 return "BUGREPORT_DEFAULT";
Nandana Dutt58d72e22018-11-16 10:30:48 +00002826 }
2827}
2828
Steven Leeb573eb82022-11-29 22:31:35 +08002829static bool IsConsentlessBugreportAllowed(const Dumpstate::DumpOptions& options) {
2830 // only BUGREPORT_TELEPHONY does not allow using consentless bugreport
2831 return !options.telephony_only;
2832}
2833
Paul Changf59c2b72020-03-10 02:08:55 +08002834static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options,
2835 bool is_screenshot_requested) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002836 // Modify com.android.shell.BugreportProgressService#isDefaultScreenshotRequired as well for
2837 // default system screenshots.
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002838 options->bugreport_mode = mode;
2839 options->bugreport_mode_string = ModeToString(mode);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002840 switch (mode) {
2841 case Dumpstate::BugreportMode::BUGREPORT_FULL:
Paul Changf59c2b72020-03-10 02:08:55 +08002842 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002843 break;
2844 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002845 // Currently, the dumpstate binder is only used by Shell to update progress.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002846 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002847 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002848 break;
2849 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002850 options->do_vibrate = false;
2851 options->is_remote_mode = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002852 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002853 break;
2854 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
Robert Ginda55ecebd2023-04-03 22:53:13 +00002855 options->do_vibrate = false;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002856 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002857 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002858 break;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002859 // TODO(b/148168577) rename TELEPHONY everywhere to CONNECTIVITY.
Nandana Dutt58d72e22018-11-16 10:30:48 +00002860 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002861 options->telephony_only = true;
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002862 options->do_progress_updates = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002863 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002864 break;
2865 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002866 options->wifi_only = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002867 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002868 break;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002869 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
2870 options->onboarding_only = true;
2871 options->do_screenshot = false;
2872 break;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002873 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2874 break;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002875 }
2876}
2877
Nandana Dutt58d72e22018-11-16 10:30:48 +00002878static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
Nandana Dutt235c6672019-11-14 15:22:32 +00002879 MYLOGI(
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002880 "do_vibrate: %d stream_to_socket: %d progress_updates_to_socket: %d do_screenshot: %d "
Rhed Jao25f50e02020-08-20 00:10:32 +08002881 "is_remote_mode: %d show_header_only: %d telephony_only: %d "
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002882 "wifi_only: %d do_progress_updates: %d fd: %d bugreport_mode: %s "
mhasankd451a472020-05-26 18:02:39 -07002883 "limited_only: %d args: %s\n",
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002884 options.do_vibrate, options.stream_to_socket, options.progress_updates_to_socket,
Paul Chang0d2aad72020-02-13 20:04:03 +08002885 options.do_screenshot, options.is_remote_mode, options.show_header_only,
Rhed Jao25f50e02020-08-20 00:10:32 +08002886 options.telephony_only, options.wifi_only,
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002887 options.do_progress_updates, options.bugreport_fd.get(),
2888 options.bugreport_mode_string.c_str(),
2889 options.limited_only, options.args.c_str());
Nandana Dutt58d72e22018-11-16 10:30:48 +00002890}
2891
Nandana Dutt54dbd672019-01-11 12:58:05 +00002892void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
Kean Mariotti306633e2022-09-05 16:30:47 +00002893 int bugreport_flags,
Nandana Dutt54dbd672019-01-11 12:58:05 +00002894 const android::base::unique_fd& bugreport_fd_in,
Paul Changf59c2b72020-03-10 02:08:55 +08002895 const android::base::unique_fd& screenshot_fd_in,
2896 bool is_screenshot_requested) {
Kean Mariotti306633e2022-09-05 16:30:47 +00002897 this->use_predumped_ui_data = bugreport_flags & BugreportFlag::BUGREPORT_USE_PREDUMPED_UI_DATA;
Gavin Corkerya44686c2022-11-23 18:16:51 +00002898 this->is_consent_deferred = bugreport_flags & BugreportFlag::BUGREPORT_FLAG_DEFER_CONSENT;
Nandana Dutt54dbd672019-01-11 12:58:05 +00002899 // Duplicate the fds because the passed in fds don't outlive the binder transaction.
Todd Frederick621533f2022-03-26 02:54:17 +00002900 bugreport_fd.reset(fcntl(bugreport_fd_in.get(), F_DUPFD_CLOEXEC, 0));
2901 screenshot_fd.reset(fcntl(screenshot_fd_in.get(), F_DUPFD_CLOEXEC, 0));
Nandana Dutt58d72e22018-11-16 10:30:48 +00002902
Paul Changf59c2b72020-03-10 02:08:55 +08002903 SetOptionsFromMode(bugreport_mode, this, is_screenshot_requested);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002904}
2905
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002906Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
2907 RunStatus status = RunStatus::OK;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002908 int c;
mhasankd451a472020-05-26 18:02:39 -07002909 while ((c = getopt(argc, argv, "dho:svqzpLPBRSV:w")) != -1) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002910 switch (c) {
2911 // clang-format off
mhasank3a4cfb42020-06-15 18:06:43 -07002912 case 'o': out_dir = optarg; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002913 case 's': stream_to_socket = true; break;
2914 case 'S': progress_updates_to_socket = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002915 case 'v': show_header_only = true; break;
2916 case 'q': do_vibrate = false; break;
Paul Chang0d2aad72020-02-13 20:04:03 +08002917 case 'p': do_screenshot = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002918 case 'P': do_progress_updates = true; break;
2919 case 'R': is_remote_mode = true; break;
mhasankd451a472020-05-26 18:02:39 -07002920 case 'L': limited_only = true; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002921 case 'V':
2922 case 'd':
2923 case 'z':
2924 // compatibility no-op
2925 break;
Nandana Dutt235864b2019-01-22 12:10:16 +00002926 case 'w':
2927 // This was already processed
2928 break;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002929 case 'h':
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002930 status = RunStatus::HELP;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002931 break;
2932 default:
2933 fprintf(stderr, "Invalid option: %c\n", c);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002934 status = RunStatus::INVALID_INPUT;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002935 break;
2936 // clang-format on
2937 }
2938 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08002939
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002940 for (int i = 0; i < argc; i++) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002941 args += argv[i];
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002942 if (i < argc - 1) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002943 args += " ";
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002944 }
2945 }
2946
2947 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
2948 optind = 1;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002949
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002950 return status;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002951}
2952
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002953bool Dumpstate::DumpOptions::ValidateOptions() const {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002954 if (bugreport_fd.get() != -1 && stream_to_socket) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002955 return false;
2956 }
2957
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002958 if ((progress_updates_to_socket || do_progress_updates) && stream_to_socket) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002959 return false;
2960 }
2961
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002962 if (is_remote_mode && (do_progress_updates || stream_to_socket)) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002963 return false;
2964 }
2965 return true;
2966}
2967
Nandana Dutt197661d2018-11-16 16:40:21 +00002968void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
2969 options_ = std::move(options);
2970}
2971
Abhijeet Kaura407fb82020-03-27 12:51:12 +00002972void Dumpstate::Initialize() {
2973 /* gets the sequential id */
2974 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
2975 id_ = ++last_id;
2976 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
2977}
2978
Nandana Duttd2f5f082019-01-18 17:13:52 +00002979Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
2980 Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
Gavin Corkerya44686c2022-11-23 18:16:51 +00002981 HandleRunStatus(status);
2982 return status;
2983}
2984
2985Dumpstate::RunStatus Dumpstate::Retrieve(int32_t calling_uid, const std::string& calling_package) {
2986 Dumpstate::RunStatus status = RetrieveInternal(calling_uid, calling_package);
2987 HandleRunStatus(status);
2988 return status;
2989}
2990
2991Dumpstate::RunStatus Dumpstate::RetrieveInternal(int32_t calling_uid,
2992 const std::string& calling_package) {
2993 consent_callback_ = new ConsentCallback();
2994 const String16 incidentcompanion("incidentcompanion");
2995 sp<android::IBinder> ics(
2996 defaultServiceManager()->checkService(incidentcompanion));
2997 android::String16 package(calling_package.c_str());
2998 if (ics != nullptr) {
2999 MYLOGD("Checking user consent via incidentcompanion service\n");
3000 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
3001 calling_uid, package, String16(), String16(),
3002 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
3003 } else {
3004 MYLOGD(
3005 "Unable to check user consent; incidentcompanion service unavailable\n");
3006 return RunStatus::USER_CONSENT_TIMED_OUT;
3007 }
3008 UserConsentResult consent_result = consent_callback_->getResult();
3009 int timeout_ms = 30 * 1000;
3010 while (consent_result == UserConsentResult::UNAVAILABLE &&
3011 consent_callback_->getElapsedTimeMs() < timeout_ms) {
3012 sleep(1);
3013 consent_result = consent_callback_->getResult();
3014 }
3015 if (consent_result == UserConsentResult::DENIED) {
3016 return RunStatus::USER_CONSENT_DENIED;
3017 }
3018 if (consent_result == UserConsentResult::UNAVAILABLE) {
3019 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3020 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3021 consent_callback_.get());
3022 return RunStatus::USER_CONSENT_TIMED_OUT;
3023 }
3024
3025 bool copy_succeeded =
3026 android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
3027 if (copy_succeeded) {
3028 android::os::UnlinkAndLogOnError(path_);
3029 }
3030 return copy_succeeded ? Dumpstate::RunStatus::OK
3031 : Dumpstate::RunStatus::ERROR;
3032}
3033
3034void Dumpstate::HandleRunStatus(Dumpstate::RunStatus status) {
3035 if (listener_ != nullptr) {
Nandana Duttbabf6c72019-01-15 14:11:12 +00003036 switch (status) {
3037 case Dumpstate::RunStatus::OK:
Gavin Corkerya44686c2022-11-23 18:16:51 +00003038 listener_->onFinished(path_.c_str());
Nandana Duttbabf6c72019-01-15 14:11:12 +00003039 break;
3040 case Dumpstate::RunStatus::HELP:
3041 break;
3042 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003043 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00003044 break;
3045 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003046 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
3047 break;
3048 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3049 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
3050 break;
3051 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
3052 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00003053 break;
3054 }
3055 }
Nandana Duttbabf6c72019-01-15 14:11:12 +00003056}
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003057void Dumpstate::Cancel() {
3058 CleanupTmpFiles();
3059 android::os::UnlinkAndLogOnError(log_path_);
3060 for (int i = 0; i < NUM_OF_DUMPS; i++) {
3061 android::os::UnlinkAndLogOnError(ds.bugreport_internal_dir_ + "/" +
3062 kDumpstateBoardFiles[i]);
3063 }
3064 tombstone_data_.clear();
3065 anr_data_.clear();
Woody Lin20767a92022-11-29 15:50:24 +08003066 shutdown_checkpoints_.clear();
Rhed Jao0daac912020-08-21 14:48:20 +08003067
3068 // Instead of shutdown the pool, we delete temporary files directly since
3069 // shutdown blocking the call.
3070 if (dump_pool_) {
3071 dump_pool_->deleteTempFiles();
3072 }
3073 if (zip_entry_tasks_) {
3074 zip_entry_tasks_->run(/*do_cancel =*/ true);
3075 }
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003076}
3077
Kean Mariotti306633e2022-09-05 16:30:47 +00003078void Dumpstate::PreDumpUiData() {
3079 MaybeSnapshotUiTraces();
3080}
3081
Nandana Dutt979388e2018-11-30 16:48:55 +00003082/*
3083 * Dumps relevant information to a bugreport based on the given options.
3084 *
3085 * The bugreport can be dumped to a file or streamed to a socket.
3086 *
3087 * How dumping to file works:
3088 * stdout is redirected to a temporary file. This will later become the main bugreport entry.
3089 * stderr is redirected a log file.
3090 *
3091 * The temporary bugreport is then populated via printfs, dumping contents of files and
3092 * output of commands to stdout.
3093 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003094 * A bunch of other files and dumps are added to the zip archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00003095 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003096 * The temporary bugreport file and the log file also get added to the archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00003097 *
mhasank2d75c442020-06-11 15:05:25 -07003098 * Bugreports are first generated in a local directory and later copied to the caller's fd
3099 * or directory if supplied.
Nandana Dutt979388e2018-11-30 16:48:55 +00003100 */
Nandana Duttd2f5f082019-01-18 17:13:52 +00003101Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
3102 const std::string& calling_package) {
Rhed Jao5377d792020-07-16 17:37:39 +08003103 DurationReporter duration_reporter("RUN INTERNAL", /* logcat_only = */true);
Nandana Dutt979388e2018-11-30 16:48:55 +00003104 LogDumpOptions(*options_);
Nandana Dutt197661d2018-11-16 16:40:21 +00003105 if (!options_->ValidateOptions()) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00003106 MYLOGE("Invalid options specified\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003107 return RunStatus::INVALID_INPUT;
3108 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003109 /* set as high priority, and protect from OOM killer */
3110 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003111
Felipe Lemed071c682016-10-20 16:48:00 -07003112 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07003113 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003114 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003115 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003116 } else {
3117 /* fallback to kernels <= 2.6.35 */
3118 oom_adj = fopen("/proc/self/oom_adj", "we");
3119 if (oom_adj) {
3120 fputs("-17", oom_adj);
3121 fclose(oom_adj);
3122 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003123 }
3124
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003125 if (version_ == VERSION_DEFAULT) {
3126 version_ = VERSION_CURRENT;
Michal Karpinski4db754f2015-12-11 18:04:32 +00003127 }
3128
Chris Morin5a50d482022-02-01 17:41:18 -08003129 if (version_ != VERSION_CURRENT) {
3130 MYLOGE("invalid version requested ('%s'); supported values are: ('%s', '%s')\n",
3131 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003132 return RunStatus::INVALID_INPUT;
Felipe Lemed071c682016-10-20 16:48:00 -07003133 }
3134
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003135 if (options_->show_header_only) {
3136 PrintHeader();
3137 return RunStatus::OK;
Felipe Lemed071c682016-10-20 16:48:00 -07003138 }
3139
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003140 MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n",
3141 calling_uid, calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003142
Felipe Leme7447d7c2016-11-03 18:12:22 -07003143 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003144 std::string stats_path =
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003145 android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003146 progress_.reset(new Progress(stats_path));
Felipe Leme7447d7c2016-11-03 18:12:22 -07003147
Sahana Raof35ed432019-07-12 10:47:52 +01003148 if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
3149 MYLOGE("Failed to acquire wake lock: %s\n", strerror(errno));
3150 } else {
3151 // Wake lock will be released automatically on process death
3152 MYLOGD("Wake lock acquired.\n");
3153 }
3154
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08003155 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07003156
Felipe Lemef0292972016-11-22 13:57:05 -08003157 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07003158 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
3159 }
3160
Kevin Jeonfa64e642023-07-27 11:36:41 -04003161 if (PropertiesHelper::IsStrictRun()) {
3162 MYLOGI(
3163 "Running on strict-run mode, which has shorter timeouts "
3164 "(to disable, call 'setprop dumpstate.strict_run false')\n");
3165 }
3166
Nandana Dutt235c6672019-11-14 15:22:32 +00003167 MYLOGI("dumpstate info: id=%d, args='%s', bugreport_mode= %s bugreport format version: %s\n",
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00003168 id_, options_->args.c_str(), options_->bugreport_mode_string.c_str(), version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08003169
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003170 do_early_screenshot_ = options_->do_progress_updates;
Felipe Lemee338bf62015-12-07 14:03:50 -08003171
Christopher Ferrised9354f2014-10-01 17:35:01 -07003172 // If we are going to use a socket, do it as early as possible
3173 // to avoid timeouts from bugreport.
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003174 if (options_->stream_to_socket || options_->progress_updates_to_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07003175 MYLOGD("Opening control socket\n");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003176 control_socket_fd_ = open_socket_fn_("dumpstate");
Nandana Dutta344cb62019-02-22 15:12:35 +00003177 if (control_socket_fd_ == -1) {
3178 return ERROR;
3179 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003180 if (options_->progress_updates_to_socket) {
3181 options_->do_progress_updates = 1;
3182 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07003183 }
3184
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003185 if (!PrepareToWriteToFile()) {
3186 return ERROR;
3187 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08003188
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003189 // Interactive, wear & telephony modes are default to true.
3190 // and may enable from cli option or when using control socket
3191 if (options_->do_progress_updates) {
3192 // clang-format off
3193 std::vector<std::string> am_args = {
3194 "--receiver-permission", "android.permission.DUMP",
3195 };
3196 // clang-format on
3197 // Send STARTED broadcast for apps that listen to bugreport generation events
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003198 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED",
3199 am_args, multiuser_get_user_id(calling_uid));
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003200 if (options_->progress_updates_to_socket) {
3201 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08003202 }
3203 }
3204
Nick Kralevichf3599b32016-01-25 15:05:16 -08003205 /* read /proc/cmdline before dropping root */
3206 FILE *cmdline = fopen("/proc/cmdline", "re");
3207 if (cmdline) {
3208 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
3209 fclose(cmdline);
3210 }
3211
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003212 if (options_->do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08003213 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05003214 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003215
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003216 if (zip_file != nullptr) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003217 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
3218 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003219 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08003220 }
3221 }
3222
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003223 int dup_stdout_fd;
3224 int dup_stderr_fd;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003225 // Redirect stderr to log_path_ for debugging.
3226 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
3227 if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
3228 return ERROR;
3229 }
3230 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
3231 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
3232 strerror(errno));
3233 }
Nandana Dutt979388e2018-11-30 16:48:55 +00003234
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003235 // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
3236 // moved into zip file later, if zipping.
3237 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
3238 // TODO: why not write to a file instead of stdout to overcome this problem?
3239 /* TODO: rather than generating a text file now and zipping it later,
3240 it would be more efficient to redirect stdout to the zip entry
3241 directly, but the libziparchive doesn't support that option yet. */
3242 if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
3243 return ERROR;
3244 }
3245 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
3246 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
3247 tmp_path_.c_str(), strerror(errno));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003248 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08003249
3250 // Don't buffer stdout
3251 setvbuf(stdout, nullptr, _IONBF, 0);
3252
Rhed Jao5377d792020-07-16 17:37:39 +08003253 // Enable the parallel run if the client requests to output to a file.
3254 EnableParallelRunIfNeeded();
3255 // Using scope guard to make sure the dump pool can be shut down correctly.
3256 auto scope_guard_to_shutdown_pool = android::base::make_scope_guard([=]() {
3257 ShutdownDumpPool();
3258 });
3259
Felipe Leme608385d2016-02-01 10:35:38 -08003260 // NOTE: there should be no stdout output until now, otherwise it would break the header.
3261 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08003262 // duration is logged into MYLOG instead.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003263 PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003264
Gavin Corkery6968f552020-11-22 18:09:05 +00003265 bool is_dumpstate_restricted = options_->telephony_only
3266 || options_->wifi_only
3267 || options_->limited_only;
3268 if (!is_dumpstate_restricted) {
Paul Chang0d2aad72020-02-13 20:04:03 +08003269 // Invoke critical dumpsys first to preserve system state, before doing anything else.
Jichao Lie89d9c12019-11-21 19:02:51 -08003270 RunDumpsysCritical();
Gavin Corkery6968f552020-11-22 18:09:05 +00003271 }
3272 MaybeTakeEarlyScreenshot();
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003273
3274 if (!is_dumpstate_restricted) {
3275 // Snapshot the system trace now (if running) to avoid that dumpstate's
3276 // own activity pushes out interesting data from the trace ring buffer.
3277 // The trace file is added to the zip by MaybeAddSystemTraceToZip().
3278 MaybeSnapshotSystemTrace();
Yohei Yukawa95305b32021-03-09 07:54:27 -08003279
Kean Mariotti306633e2022-09-05 16:30:47 +00003280 // Snapshot the UI traces now (if running).
3281 // The trace files will be added to bugreport later.
3282 MaybeSnapshotUiTraces();
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003283 }
Gavin Corkery6968f552020-11-22 18:09:05 +00003284 onUiIntensiveBugreportDumpsFinished(calling_uid);
3285 MaybeCheckUserConsent(calling_uid, calling_package);
3286 if (options_->telephony_only) {
3287 DumpstateTelephonyOnly(calling_package);
3288 } else if (options_->wifi_only) {
3289 DumpstateWifiOnly();
3290 } else if (options_->limited_only) {
3291 DumpstateLimitedOnly();
Elis Elliott8e401ad2023-08-08 11:18:59 +00003292 } else if (options_->onboarding_only) {
3293 DumpstateOnboardingOnly();
Gavin Corkery6968f552020-11-22 18:09:05 +00003294 } else {
Nandana Dutt4be45d12018-09-26 15:04:23 +01003295 // Dump state for the default case. This also drops root.
Jichao Lie89d9c12019-11-21 19:02:51 -08003296 RunStatus s = DumpstateDefaultAfterCritical();
Nandana Dutt5c390032019-03-12 10:52:56 +00003297 if (s != RunStatus::OK) {
Nandana Duttaac6f582019-07-26 14:32:47 +01003298 if (s == RunStatus::USER_CONSENT_DENIED) {
Nandana Dutt5c390032019-03-12 10:52:56 +00003299 HandleUserConsentDenied();
3300 }
3301 return s;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08003302 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07003303 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07003304
Felipe Leme55b42a62015-11-10 17:39:08 -08003305 /* close output if needed */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003306 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003307
Abhijeet Kaure370d682019-10-01 16:49:30 +01003308 // Zip the (now complete) .tmp file within the internal directory.
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003309 ATRACE_BEGIN("FinalizeFile");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003310 FinalizeFile();
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003311 ATRACE_END();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003312
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003313 // Share the final file with the caller if the user has consented or Shell is the caller.
Nandana Duttd2f5f082019-01-18 17:13:52 +00003314 Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
Gavin Corkerya44686c2022-11-23 18:16:51 +00003315 if (CalledByApi() && !options_->is_consent_deferred) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003316 status = CopyBugreportIfUserConsented(calling_uid);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003317 if (status != Dumpstate::RunStatus::OK &&
3318 status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3319 // Do an early return if there were errors. We make an exception for consent
3320 // timing out because it's possible the user got distracted. In this case the
3321 // bugreport is not shared but made available for manual retrieval.
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003322 MYLOGI("User denied consent. Returning\n");
Nandana Duttd2f5f082019-01-18 17:13:52 +00003323 return status;
3324 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003325 if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3326 MYLOGI(
3327 "Did not receive user consent yet."
3328 " Will not copy the bugreport artifacts to caller.\n");
Abhijeet Kaur57627412019-04-17 16:00:09 +01003329 const String16 incidentcompanion("incidentcompanion");
3330 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
3331 if (ics != nullptr) {
3332 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3333 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3334 consent_callback_.get());
3335 } else {
3336 MYLOGD("Unable to cancel user consent; incidentcompanion service unavailable\n");
3337 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003338 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003339 }
3340
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003341 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003342 if (options_->do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09003343 for (int i = 0; i < 3; i++) {
3344 Vibrate(75);
3345 usleep((75 + 50) * 1000);
3346 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003347 }
3348
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003349 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
3350 progress_->GetInitialMax());
3351 progress_->Save();
3352 MYLOGI("done (id %d)\n", id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003353
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003354 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08003355
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003356 if (control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07003357 MYLOGD("Closing control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003358 close(control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07003359 }
3360
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003361 tombstone_data_.clear();
3362 anr_data_.clear();
Woody Lin20767a92022-11-29 15:50:24 +08003363 shutdown_checkpoints_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01003364
Nandana Duttd2f5f082019-01-18 17:13:52 +00003365 return (consent_callback_ != nullptr &&
3366 consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
3367 ? USER_CONSENT_TIMED_OUT
3368 : RunStatus::OK;
3369}
3370
Paul Chang0d2aad72020-02-13 20:04:03 +08003371void Dumpstate::MaybeTakeEarlyScreenshot() {
3372 if (!options_->do_screenshot || !do_early_screenshot_) {
3373 return;
3374 }
3375
3376 TakeScreenshot();
3377}
3378
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003379void Dumpstate::MaybeSnapshotSystemTrace() {
3380 // If a background system trace is happening and is marked as "suitable for
3381 // bugreport" (i.e. bugreport_score > 0 in the trace config), this command
3382 // will stop it and serialize into SYSTEM_TRACE_SNAPSHOT. In the (likely)
3383 // case that no trace is ongoing, this command is a no-op.
3384 // Note: this should not be enqueued as we need to freeze the trace before
3385 // dumpstate starts. Otherwise the trace ring buffers will contain mostly
3386 // the dumpstate's own activity which is irrelevant.
3387 int res = RunCommand(
3388 "SERIALIZE PERFETTO TRACE",
3389 {"perfetto", "--save-for-bugreport"},
3390 CommandOptions::WithTimeout(10)
3391 .DropRoot()
3392 .CloseAllFileDescriptorsOnExec()
3393 .Build());
3394 has_system_trace_ = res == 0;
3395 // MaybeAddSystemTraceToZip() will take care of copying the trace in the zip
3396 // file in the later stages.
3397}
3398
Kean Mariotti306633e2022-09-05 16:30:47 +00003399void Dumpstate::MaybeSnapshotUiTraces() {
3400 if (PropertiesHelper::IsUserBuild() || options_->use_predumped_ui_data) {
3401 return;
3402 }
3403
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003404 const std::vector<std::vector<std::string>> dumpTracesForBugReportCommands = {
3405 {"dumpsys", "activity", "service", "SystemUIService", "WMShell", "protolog",
3406 "save-for-bugreport"},
3407 {"dumpsys", "activity", "service", "SystemUIService", "WMShell", "transitions", "tracing",
3408 "save-for-bugreport"},
3409 {"cmd", "input_method", "tracing", "save-for-bugreport"},
3410 {"cmd", "window", "tracing", "save-for-bugreport"},
3411 {"cmd", "window", "shell", "tracing", "save-for-bugreport"},
3412 };
Hongwei Wang39229132023-01-24 15:09:59 -08003413
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003414 for (const auto& command : dumpTracesForBugReportCommands) {
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003415 RunCommand(
3416 // Empty name because it's not intended to be classified as a bugreport section.
3417 // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003418 "", command,
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003419 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
3420 }
Kean Mariotti306633e2022-09-05 16:30:47 +00003421
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003422 // This command needs to be run as root
Kean Mariotti306633e2022-09-05 16:30:47 +00003423 static const auto SURFACEFLINGER_COMMAND_SAVE_ALL_TRACES = std::vector<std::string> {
3424 "service", "call", "SurfaceFlinger", "1042"
3425 };
3426 // Empty name because it's not intended to be classified as a bugreport section.
3427 // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
3428 RunCommand(
3429 "", SURFACEFLINGER_COMMAND_SAVE_ALL_TRACES,
3430 CommandOptions::WithTimeout(10).Always().AsRoot().RedirectStderr().Build());
3431}
3432
3433void Dumpstate::MaybePostProcessUiTraces() {
3434 if (PropertiesHelper::IsUserBuild()) {
3435 return;
3436 }
3437
3438 RunCommand(
3439 // Empty name because it's not intended to be classified as a bugreport section.
3440 // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
3441 "", {
3442 "/system/xbin/su", "system",
3443 "/system/bin/layertracegenerator",
3444 "/data/misc/wmtrace/transactions_trace.winscope",
3445 "/data/misc/wmtrace/layers_trace_from_transactions.winscope"
3446 },
3447 CommandOptions::WithTimeout(120).Always().RedirectStderr().Build());
3448}
3449
3450void Dumpstate::MaybeAddUiTracesToZip() {
3451 if (PropertiesHelper::IsUserBuild()) {
3452 return;
3453 }
3454
3455 ds.AddDir(WMTRACE_DATA_DIR, false);
Yohei Yukawa95305b32021-03-09 07:54:27 -08003456}
3457
Paul Changeb4b4642020-05-28 22:05:47 +08003458void Dumpstate::onUiIntensiveBugreportDumpsFinished(int32_t calling_uid) {
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003459 if (multiuser_get_app_id(calling_uid) == AID_SHELL || !CalledByApi()) {
Paul Changc490e662020-04-11 18:14:09 +08003460 return;
3461 }
3462 if (listener_ != nullptr) {
3463 // Let listener know ui intensive bugreport dumps are finished, then it can do event
3464 // handling if required.
Paul Changeb4b4642020-05-28 22:05:47 +08003465 listener_->onUiIntensiveBugreportDumpsFinished();
Paul Changc490e662020-04-11 18:14:09 +08003466 }
3467}
3468
Jichao Lie89d9c12019-11-21 19:02:51 -08003469void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) {
Gavin Corkerya44686c2022-11-23 18:16:51 +00003470 if (multiuser_get_app_id(calling_uid) == AID_SHELL ||
3471 !CalledByApi() || options_->is_consent_deferred) {
3472 // No need to get consent for shell triggered dumpstates, or not
3473 // through bugreporting API (i.e. no fd to copy back), or when consent
3474 // is deferred.
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003475 return;
3476 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003477 consent_callback_ = new ConsentCallback();
3478 const String16 incidentcompanion("incidentcompanion");
3479 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
Jichao Lie89d9c12019-11-21 19:02:51 -08003480 android::String16 package(calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003481 if (ics != nullptr) {
3482 MYLOGD("Checking user consent via incidentcompanion service\n");
Steven Leeb573eb82022-11-29 22:31:35 +08003483 int flags = 0x1; // IncidentManager.FLAG_CONFIRMATION_DIALOG
3484 if (IsConsentlessBugreportAllowed(*options_)) {
3485 flags |= 0x2; // IncidentManager.FLAG_ALLOW_CONSENTLESS_BUGREPORT
3486 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003487 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
Steven Leeb573eb82022-11-29 22:31:35 +08003488 calling_uid, package, String16(), String16(), flags, consent_callback_.get());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003489 } else {
3490 MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
3491 }
3492}
3493
Nandana Dutt5c390032019-03-12 10:52:56 +00003494bool Dumpstate::IsUserConsentDenied() const {
3495 return ds.consent_callback_ != nullptr &&
3496 ds.consent_callback_->getResult() == UserConsentResult::DENIED;
3497}
3498
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01003499bool Dumpstate::CalledByApi() const {
3500 return ds.options_->bugreport_fd.get() != -1 ? true : false;
3501}
3502
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003503void Dumpstate::CleanupTmpFiles() {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003504 android::os::UnlinkAndLogOnError(tmp_path_);
3505 android::os::UnlinkAndLogOnError(screenshot_path_);
3506 android::os::UnlinkAndLogOnError(path_);
Gavin Corkery789d7a52021-02-24 23:52:35 +00003507 if (dump_traces_path != nullptr) {
3508 android::os::UnlinkAndLogOnError(dump_traces_path);
3509 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003510}
3511
Rhed Jao5377d792020-07-16 17:37:39 +08003512void Dumpstate::EnableParallelRunIfNeeded() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003513 if (!PropertiesHelper::IsParallelRun()) {
Rhed Jao5377d792020-07-16 17:37:39 +08003514 return;
3515 }
3516 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003517 zip_entry_tasks_ = std::make_unique<TaskQueue>();
Rhed Jao5377d792020-07-16 17:37:39 +08003518}
3519
3520void Dumpstate::ShutdownDumpPool() {
3521 if (dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08003522 dump_pool_.reset();
Rhed Jao5377d792020-07-16 17:37:39 +08003523 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003524 if (zip_entry_tasks_) {
3525 zip_entry_tasks_->run(/* do_cancel = */true);
3526 zip_entry_tasks_ = nullptr;
3527 }
3528}
3529
3530void Dumpstate::EnqueueAddZipEntryAndCleanupIfNeeded(const std::string& entry_name,
3531 const std::string& entry_path) {
3532 auto func_add_zip_entry_and_cleanup = [=](bool task_cancelled) {
3533 if (!task_cancelled) {
3534 AddZipEntry(entry_name, entry_path);
3535 }
3536 android::os::UnlinkAndLogOnError(entry_path);
3537 };
3538 if (zip_entry_tasks_) {
3539 // Enqueues AddZipEntryAndCleanup function if the parallel run is enabled.
3540 zip_entry_tasks_->add(func_add_zip_entry_and_cleanup, _1);
3541 } else {
3542 // Invokes AddZipEntryAndCleanup immediately
3543 std::invoke(func_add_zip_entry_and_cleanup, /* task_cancelled = */false);
3544 }
Rhed Jao5377d792020-07-16 17:37:39 +08003545}
3546
Nandana Duttd2f5f082019-01-18 17:13:52 +00003547Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
3548 MYLOGD("User denied consent; deleting files and returning\n");
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003549 CleanupTmpFiles();
Nandana Duttd2f5f082019-01-18 17:13:52 +00003550 return USER_CONSENT_DENIED;
3551}
3552
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003553Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented(int32_t calling_uid) {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003554 // If the caller has asked to copy the bugreport over to their directory, we need explicit
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003555 // user consent (unless the caller is Shell).
3556 UserConsentResult consent_result;
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003557 if (multiuser_get_app_id(calling_uid) == AID_SHELL) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003558 consent_result = UserConsentResult::APPROVED;
3559 } else {
3560 consent_result = consent_callback_->getResult();
3561 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003562 if (consent_result == UserConsentResult::UNAVAILABLE) {
3563 // User has not responded yet.
3564 uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
Hunter Knepshield70610fa2020-01-03 15:27:33 -08003565 // Telephony is a fast report type, particularly on user builds where information may be
3566 // more aggressively limited. To give the user time to read the consent dialog, increase the
3567 // timeout.
3568 uint64_t timeout_ms = options_->telephony_only ? TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS
3569 : USER_CONSENT_TIMEOUT_MS;
3570 if (elapsed_ms < timeout_ms) {
3571 uint delay_seconds = (timeout_ms - elapsed_ms) / 1000;
Nandana Duttd2f5f082019-01-18 17:13:52 +00003572 MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
3573 sleep(delay_seconds);
3574 }
3575 consent_result = consent_callback_->getResult();
3576 }
3577 if (consent_result == UserConsentResult::DENIED) {
3578 // User has explicitly denied sharing with the app. To be safe delete the
3579 // internal bugreport & tmp files.
3580 return HandleUserConsentDenied();
3581 }
3582 if (consent_result == UserConsentResult::APPROVED) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00003583 bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
3584 if (copy_succeeded) {
3585 android::os::UnlinkAndLogOnError(path_);
Abhijeet Kaur9ce94672020-04-01 17:22:36 +01003586 if (options_->do_screenshot &&
3587 options_->screenshot_fd.get() != -1 &&
3588 !options_->is_screenshot_copied) {
3589 copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
3590 options_->screenshot_fd.get());
3591 options_->is_screenshot_copied = copy_succeeded;
3592 if (copy_succeeded) {
3593 android::os::UnlinkAndLogOnError(screenshot_path_);
3594 }
3595 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003596 }
3597 return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
3598 } else if (consent_result == UserConsentResult::UNAVAILABLE) {
3599 // consent_result is still UNAVAILABLE. The user has likely not responded yet.
3600 // Since we do not have user consent to share the bugreport it does not get
3601 // copied over to the calling app but remains in the internal directory from
3602 // where the user can manually pull it.
Paul Changce644212021-05-11 16:06:45 +08003603 std::string final_path = GetPath(".zip");
3604 bool copy_succeeded = android::os::CopyFileToFile(path_, final_path);
3605 if (copy_succeeded) {
3606 android::os::UnlinkAndLogOnError(path_);
3607 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003608 return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
3609 }
3610 // Unknown result; must be a programming error.
3611 MYLOGE("Unknown user consent result:%d\n", consent_result);
3612 return Dumpstate::RunStatus::ERROR;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003613}
3614
Nandana Duttf02564e2019-02-15 15:24:24 +00003615Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003616 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
3617 Dumpstate::RunStatus status = options->Initialize(argc, argv);
3618 if (status == Dumpstate::RunStatus::OK) {
Nandana Duttf02564e2019-02-15 15:24:24 +00003619 SetOptions(std::move(options));
Nandana Duttd2f5f082019-01-18 17:13:52 +00003620 // When directly running dumpstate binary, the output is not expected to be written
3621 // to any external file descriptor.
Nandana Duttf02564e2019-02-15 15:24:24 +00003622 assert(options_->bugreport_fd.get() == -1);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003623
3624 // calling_uid and calling_package are for user consent to share the bugreport with
Abhijeet Kaura407fb82020-03-27 12:51:12 +00003625 // an app; they are irrelevant here because bugreport is triggered via command line.
3626 // Update Last ID before calling Run().
3627 Initialize();
Nikhil Kumarb70622a2023-06-15 15:37:19 +01003628 status = Run(0 /* calling_uid */, "" /* calling_package */);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003629 }
Nandana Duttf02564e2019-02-15 15:24:24 +00003630 return status;
3631}
3632
3633/* Main entry point for dumpstate binary. */
3634int run_main(int argc, char* argv[]) {
3635 Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003636
3637 switch (status) {
3638 case Dumpstate::RunStatus::OK:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003639 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003640 case Dumpstate::RunStatus::HELP:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003641 ShowUsage();
3642 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003643 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003644 fprintf(stderr, "Invalid combination of args\n");
3645 ShowUsage();
3646 exit(1);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003647 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003648 FALLTHROUGH_INTENDED;
3649 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3650 FALLTHROUGH_INTENDED;
3651 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003652 exit(2);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003653 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003654}
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003655
3656// TODO(111441001): Default DumpOptions to sensible values.
3657Dumpstate::Dumpstate(const std::string& version)
3658 : pid_(getpid()),
3659 options_(new Dumpstate::DumpOptions()),
Nandana Dutt402a8392019-06-14 14:25:13 +01003660 last_reported_percent_progress_(0),
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003661 version_(version),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003662 now_(time(nullptr)),
3663 open_socket_fn_(open_socket) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003664}
3665
3666Dumpstate& Dumpstate::GetInstance() {
3667 static Dumpstate singleton_(android::base::GetProperty("dumpstate.version", VERSION_CURRENT));
3668 return singleton_;
3669}
3670
Rhed Jao5377d792020-07-16 17:37:39 +08003671DurationReporter::DurationReporter(const std::string& title, bool logcat_only, bool verbose,
3672 int duration_fd) : title_(title), logcat_only_(logcat_only), verbose_(verbose),
3673 duration_fd_(duration_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003674 if (!title_.empty()) {
3675 started_ = Nanotime();
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003676 if (title_.find("SHOW MAP") == std::string::npos) {
3677 ATRACE_ASYNC_BEGIN(title_.c_str(), 0);
3678 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003679 }
3680}
3681
3682DurationReporter::~DurationReporter() {
3683 if (!title_.empty()) {
3684 float elapsed = (float)(Nanotime() - started_) / NANOS_PER_SEC;
chenqiwuaf8b2d92019-12-12 18:53:51 +08003685 if (elapsed >= .5f || verbose_) {
3686 MYLOGD("Duration of '%s': %.2fs\n", title_.c_str(), elapsed);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003687 }
chenqiwuaf8b2d92019-12-12 18:53:51 +08003688 if (!logcat_only_) {
3689 // Use "Yoda grammar" to make it easier to grep|sort sections.
Rhed Jao5377d792020-07-16 17:37:39 +08003690 dprintf(duration_fd_, "------ %.3fs was the duration of '%s' ------\n",
3691 elapsed, title_.c_str());
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003692 }
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003693 if (title_.find("SHOW MAP") == std::string::npos) {
3694 ATRACE_ASYNC_END(title_.c_str(), 0);
3695 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003696 }
3697}
3698
3699const int32_t Progress::kDefaultMax = 5000;
3700
3701Progress::Progress(const std::string& path) : Progress(Progress::kDefaultMax, 1.1, path) {
3702}
3703
3704Progress::Progress(int32_t initial_max, int32_t progress, float growth_factor)
3705 : Progress(initial_max, growth_factor, "") {
3706 progress_ = progress;
3707}
3708
3709Progress::Progress(int32_t initial_max, float growth_factor, const std::string& path)
3710 : initial_max_(initial_max),
3711 progress_(0),
3712 max_(initial_max),
3713 growth_factor_(growth_factor),
3714 n_runs_(0),
3715 average_max_(0),
3716 path_(path) {
3717 if (!path_.empty()) {
3718 Load();
3719 }
3720}
3721
3722void Progress::Load() {
3723 MYLOGD("Loading stats from %s\n", path_.c_str());
3724 std::string content;
3725 if (!android::base::ReadFileToString(path_, &content)) {
3726 MYLOGI("Could not read stats from %s; using max of %d\n", path_.c_str(), max_);
3727 return;
3728 }
3729 if (content.empty()) {
3730 MYLOGE("No stats (empty file) on %s; using max of %d\n", path_.c_str(), max_);
3731 return;
3732 }
3733 std::vector<std::string> lines = android::base::Split(content, "\n");
3734
3735 if (lines.size() < 1) {
3736 MYLOGE("Invalid stats on file %s: not enough lines (%d). Using max of %d\n", path_.c_str(),
3737 (int)lines.size(), max_);
3738 return;
3739 }
3740 char* ptr;
3741 n_runs_ = strtol(lines[0].c_str(), &ptr, 10);
3742 average_max_ = strtol(ptr, nullptr, 10);
3743 if (n_runs_ <= 0 || average_max_ <= 0 || n_runs_ > STATS_MAX_N_RUNS ||
3744 average_max_ > STATS_MAX_AVERAGE) {
3745 MYLOGE("Invalid stats line on file %s: %s\n", path_.c_str(), lines[0].c_str());
3746 initial_max_ = Progress::kDefaultMax;
3747 } else {
3748 initial_max_ = average_max_;
3749 }
3750 max_ = initial_max_;
3751
3752 MYLOGI("Average max progress: %d in %d runs; estimated max: %d\n", average_max_, n_runs_, max_);
3753}
3754
3755void Progress::Save() {
3756 int32_t total = n_runs_ * average_max_ + progress_;
3757 int32_t runs = n_runs_ + 1;
3758 int32_t average = floor(((float)total) / runs);
3759 MYLOGI("Saving stats (total=%d, runs=%d, average=%d) on %s\n", total, runs, average,
3760 path_.c_str());
3761 if (path_.empty()) {
3762 return;
3763 }
3764
3765 std::string content = android::base::StringPrintf("%d %d\n", runs, average);
3766 if (!android::base::WriteStringToFile(content, path_)) {
3767 MYLOGE("Could not save stats on %s\n", path_.c_str());
3768 }
3769}
3770
3771int32_t Progress::Get() const {
3772 return progress_;
3773}
3774
3775bool Progress::Inc(int32_t delta_sec) {
3776 bool changed = false;
3777 if (delta_sec >= 0) {
3778 progress_ += delta_sec;
3779 if (progress_ > max_) {
3780 int32_t old_max = max_;
3781 max_ = floor((float)progress_ * growth_factor_);
3782 MYLOGD("Adjusting max progress from %d to %d\n", old_max, max_);
3783 changed = true;
3784 }
3785 }
3786 return changed;
3787}
3788
3789int32_t Progress::GetMax() const {
3790 return max_;
3791}
3792
3793int32_t Progress::GetInitialMax() const {
3794 return initial_max_;
3795}
3796
3797void Progress::Dump(int fd, const std::string& prefix) const {
3798 const char* pr = prefix.c_str();
3799 dprintf(fd, "%sprogress: %d\n", pr, progress_);
3800 dprintf(fd, "%smax: %d\n", pr, max_);
3801 dprintf(fd, "%sinitial_max: %d\n", pr, initial_max_);
3802 dprintf(fd, "%sgrowth_factor: %0.2f\n", pr, growth_factor_);
3803 dprintf(fd, "%spath: %s\n", pr, path_.c_str());
3804 dprintf(fd, "%sn_runs: %d\n", pr, n_runs_);
3805 dprintf(fd, "%saverage_max: %d\n", pr, average_max_);
3806}
3807
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003808std::string Dumpstate::GetPath(const std::string& suffix) const {
3809 return GetPath(bugreport_internal_dir_, suffix);
3810}
3811
3812std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
3813 return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
3814 name_.c_str(), suffix.c_str());
3815}
3816
3817void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
3818 progress_ = std::move(progress);
3819}
3820
3821void for_each_userid(void (*func)(int), const char *header) {
3822 std::string title = header == nullptr ? "for_each_userid" : android::base::StringPrintf(
3823 "for_each_userid(%s)", header);
3824 DurationReporter duration_reporter(title);
3825 if (PropertiesHelper::IsDryRun()) return;
3826
3827 DIR *d;
3828 struct dirent *de;
3829
3830 if (header) printf("\n------ %s ------\n", header);
3831 func(0);
3832
3833 if (!(d = opendir("/data/system/users"))) {
3834 printf("Failed to open /data/system/users (%s)\n", strerror(errno));
3835 return;
3836 }
3837
3838 while ((de = readdir(d))) {
3839 int userid;
3840 if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
3841 continue;
3842 }
3843 func(userid);
3844 }
3845
3846 closedir(d);
3847}
3848
3849static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
3850 DIR *d;
3851 struct dirent *de;
3852
3853 if (!(d = opendir("/proc"))) {
3854 printf("Failed to open /proc (%s)\n", strerror(errno));
3855 return;
3856 }
3857
3858 if (header) printf("\n------ %s ------\n", header);
3859 while ((de = readdir(d))) {
3860 if (ds.IsUserConsentDenied()) {
3861 MYLOGE(
3862 "Returning early because user denied consent to share bugreport with calling app.");
3863 closedir(d);
3864 return;
3865 }
3866 int pid;
3867 int fd;
3868 char cmdpath[255];
3869 char cmdline[255];
3870
3871 if (!(pid = atoi(de->d_name))) {
3872 continue;
3873 }
3874
3875 memset(cmdline, 0, sizeof(cmdline));
3876
3877 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
3878 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3879 TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
3880 close(fd);
3881 if (cmdline[0]) {
3882 helper(pid, cmdline, arg);
3883 continue;
3884 }
3885 }
3886
3887 // if no cmdline, a kernel thread has comm
3888 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
3889 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3890 TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
3891 close(fd);
3892 if (cmdline[1]) {
3893 cmdline[0] = '[';
3894 size_t len = strcspn(cmdline, "\f\b\r\n");
3895 cmdline[len] = ']';
3896 cmdline[len+1] = '\0';
3897 }
3898 }
3899 if (!cmdline[0]) {
3900 strcpy(cmdline, "N/A");
3901 }
3902 helper(pid, cmdline, arg);
3903 }
3904
3905 closedir(d);
3906}
3907
3908static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
3909 for_each_pid_func *func = (for_each_pid_func*) arg;
3910 func(pid, cmdline);
3911}
3912
3913void for_each_pid(for_each_pid_func func, const char *header) {
3914 std::string title = header == nullptr ? "for_each_pid"
3915 : android::base::StringPrintf("for_each_pid(%s)", header);
3916 DurationReporter duration_reporter(title);
3917 if (PropertiesHelper::IsDryRun()) return;
3918
3919 __for_each_pid(for_each_pid_helper, header, (void *) func);
3920}
3921
3922static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
3923 DIR *d;
3924 struct dirent *de;
3925 char taskpath[255];
3926 for_each_tid_func *func = (for_each_tid_func *) arg;
3927
3928 snprintf(taskpath, sizeof(taskpath), "/proc/%d/task", pid);
3929
3930 if (!(d = opendir(taskpath))) {
3931 printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
3932 return;
3933 }
3934
3935 func(pid, pid, cmdline);
3936
3937 while ((de = readdir(d))) {
3938 if (ds.IsUserConsentDenied()) {
3939 MYLOGE(
3940 "Returning early because user denied consent to share bugreport with calling app.");
3941 closedir(d);
3942 return;
3943 }
3944 int tid;
3945 int fd;
3946 char commpath[255];
3947 char comm[255];
3948
3949 if (!(tid = atoi(de->d_name))) {
3950 continue;
3951 }
3952
3953 if (tid == pid)
3954 continue;
3955
3956 snprintf(commpath, sizeof(commpath), "/proc/%d/comm", tid);
3957 memset(comm, 0, sizeof(comm));
3958 if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
3959 strcpy(comm, "N/A");
3960 } else {
3961 char *c;
3962 TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
3963 close(fd);
3964
3965 c = strrchr(comm, '\n');
3966 if (c) {
3967 *c = '\0';
3968 }
3969 }
3970 func(pid, tid, comm);
3971 }
3972
3973 closedir(d);
3974}
3975
3976void for_each_tid(for_each_tid_func func, const char *header) {
3977 std::string title = header == nullptr ? "for_each_tid"
3978 : android::base::StringPrintf("for_each_tid(%s)", header);
3979 DurationReporter duration_reporter(title);
3980
3981 if (PropertiesHelper::IsDryRun()) return;
3982
3983 __for_each_pid(for_each_tid_helper, header, (void *) func);
3984}
3985
3986void show_wchan(int pid, int tid, const char *name) {
3987 if (PropertiesHelper::IsDryRun()) return;
3988
3989 char path[255];
3990 char buffer[255];
3991 int fd, ret, save_errno;
3992 char name_buffer[255];
3993
3994 memset(buffer, 0, sizeof(buffer));
3995
3996 snprintf(path, sizeof(path), "/proc/%d/wchan", tid);
3997 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
3998 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
3999 return;
4000 }
4001
4002 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
4003 save_errno = errno;
4004 close(fd);
4005
4006 if (ret < 0) {
4007 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
4008 return;
4009 }
4010
4011 snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
4012 pid == tid ? 0 : 3, "", name);
4013
4014 printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
4015
4016 return;
4017}
4018
4019// print time in centiseconds
4020static void snprcent(char *buffer, size_t len, size_t spc,
4021 unsigned long long time) {
4022 static long hz; // cache discovered hz
4023
4024 if (hz <= 0) {
4025 hz = sysconf(_SC_CLK_TCK);
4026 if (hz <= 0) {
4027 hz = 1000;
4028 }
4029 }
4030
4031 // convert to centiseconds
4032 time = (time * 100 + (hz / 2)) / hz;
4033
4034 char str[16];
4035
4036 snprintf(str, sizeof(str), " %llu.%02u",
4037 time / 100, (unsigned)(time % 100));
4038 size_t offset = strlen(buffer);
4039 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
4040 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
4041}
4042
4043// print permille as a percent
4044static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
4045 char str[16];
4046
4047 snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
4048 size_t offset = strlen(buffer);
4049 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
4050 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
4051}
4052
4053void show_showtime(int pid, const char *name) {
4054 if (PropertiesHelper::IsDryRun()) return;
4055
4056 char path[255];
4057 char buffer[1023];
4058 int fd, ret, save_errno;
4059
4060 memset(buffer, 0, sizeof(buffer));
4061
4062 snprintf(path, sizeof(path), "/proc/%d/stat", pid);
4063 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
4064 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
4065 return;
4066 }
4067
4068 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
4069 save_errno = errno;
4070 close(fd);
4071
4072 if (ret < 0) {
4073 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
4074 return;
4075 }
4076
4077 // field 14 is utime
4078 // field 15 is stime
4079 // field 42 is iotime
4080 unsigned long long utime = 0, stime = 0, iotime = 0;
4081 if (sscanf(buffer,
4082 "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
4083 "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
4084 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
4085 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
4086 &utime, &stime, &iotime) != 3) {
4087 return;
4088 }
4089
4090 unsigned long long total = utime + stime;
4091 if (!total) {
4092 return;
4093 }
4094
4095 unsigned permille = (iotime * 1000 + (total / 2)) / total;
4096 if (permille > 1000) {
4097 permille = 1000;
4098 }
4099
4100 // try to beautify and stabilize columns at <80 characters
4101 snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
4102 if ((name[0] != '[') || utime) {
4103 snprcent(buffer, sizeof(buffer), 57, utime);
4104 }
4105 snprcent(buffer, sizeof(buffer), 65, stime);
4106 if ((name[0] != '[') || iotime) {
4107 snprcent(buffer, sizeof(buffer), 73, iotime);
4108 }
4109 if (iotime) {
4110 snprdec(buffer, sizeof(buffer), 79, permille);
4111 }
4112 puts(buffer); // adds a trailing newline
4113
4114 return;
4115}
4116
4117void do_dmesg() {
4118 const char *title = "KERNEL LOG (dmesg)";
4119 DurationReporter duration_reporter(title);
4120 printf("------ %s ------\n", title);
4121
4122 if (PropertiesHelper::IsDryRun()) return;
4123
4124 /* Get size of kernel buffer */
4125 int size = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
4126 if (size <= 0) {
4127 printf("Unexpected klogctl return value: %d\n\n", size);
4128 return;
4129 }
4130 char *buf = (char *) malloc(size + 1);
4131 if (buf == nullptr) {
4132 printf("memory allocation failed\n\n");
4133 return;
4134 }
4135 int retval = klogctl(KLOG_READ_ALL, buf, size);
4136 if (retval < 0) {
4137 printf("klogctl failure\n\n");
4138 free(buf);
4139 return;
4140 }
4141 buf[retval] = '\0';
4142 printf("%s\n\n", buf);
4143 free(buf);
4144 return;
4145}
4146
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004147int Dumpstate::DumpFile(const std::string& title, const std::string& path) {
4148 DurationReporter duration_reporter(title);
4149
4150 int status = DumpFileToFd(STDOUT_FILENO, title, path);
4151
4152 UpdateProgress(WEIGHT_FILE);
4153
4154 return status;
4155}
4156
4157int read_file_as_long(const char *path, long int *output) {
4158 int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
4159 if (fd < 0) {
4160 int err = errno;
4161 MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
4162 return -1;
4163 }
4164 char buffer[50];
4165 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
4166 if (bytes_read == -1) {
4167 MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
4168 return -2;
4169 }
4170 if (bytes_read == 0) {
4171 MYLOGE("File %s is empty\n", path);
4172 return -3;
4173 }
4174 *output = atoi(buffer);
4175 return 0;
4176}
4177
4178/* calls skip to gate calling dump_from_fd recursively
4179 * in the specified directory. dump_from_fd defaults to
4180 * dump_file_from_fd above when set to NULL. skip defaults
4181 * to false when set to NULL. dump_from_fd will always be
4182 * called with title NULL.
4183 */
4184int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
4185 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4186 DurationReporter duration_reporter(title);
4187 DIR *dirp;
4188 struct dirent *d;
4189 char *newpath = nullptr;
4190 const char *slash = "/";
4191 int retval = 0;
4192
4193 if (!title.empty()) {
4194 printf("------ %s (%s) ------\n", title.c_str(), dir);
4195 }
4196 if (PropertiesHelper::IsDryRun()) return 0;
4197
4198 if (dir[strlen(dir) - 1] == '/') {
4199 ++slash;
4200 }
4201 dirp = opendir(dir);
4202 if (dirp == nullptr) {
4203 retval = -errno;
4204 MYLOGE("%s: %s\n", dir, strerror(errno));
4205 return retval;
4206 }
4207
4208 if (!dump_from_fd) {
4209 dump_from_fd = dump_file_from_fd;
4210 }
4211 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4212 if ((d->d_name[0] == '.')
4213 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4214 || (d->d_name[1] == '\0'))) {
4215 continue;
4216 }
4217 asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
4218 (d->d_type == DT_DIR) ? "/" : "");
4219 if (!newpath) {
4220 retval = -errno;
4221 continue;
4222 }
4223 if (skip && (*skip)(newpath)) {
4224 continue;
4225 }
4226 if (d->d_type == DT_DIR) {
4227 int ret = dump_files("", newpath, skip, dump_from_fd);
4228 if (ret < 0) {
4229 retval = ret;
4230 }
4231 continue;
4232 }
4233 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
4234 if (fd.get() < 0) {
4235 retval = -1;
4236 printf("*** %s: %s\n", newpath, strerror(errno));
4237 continue;
4238 }
4239 (*dump_from_fd)(nullptr, newpath, fd.get());
4240 }
4241 closedir(dirp);
4242 if (!title.empty()) {
4243 printf("\n");
4244 }
4245 return retval;
4246}
4247
4248/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
4249 * it's possible to avoid issues where opening the file itself can get
4250 * stuck.
4251 */
4252int dump_file_from_fd(const char *title, const char *path, int fd) {
4253 if (PropertiesHelper::IsDryRun()) return 0;
4254
4255 int flags = fcntl(fd, F_GETFL);
4256 if (flags == -1) {
4257 printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
4258 return -1;
4259 } else if (!(flags & O_NONBLOCK)) {
4260 printf("*** %s: fd must have O_NONBLOCK set.\n", path);
4261 return -1;
4262 }
4263 return DumpFileFromFdToFd(title, path, fd, STDOUT_FILENO, PropertiesHelper::IsDryRun());
4264}
4265
4266int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004267 const CommandOptions& options, bool verbose_duration, int out_fd) {
4268 DurationReporter duration_reporter(title, false /* logcat_only */,
4269 verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004270
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004271 int status = RunCommandToFd(out_fd, title, full_command, options);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004272
4273 /* TODO: for now we're simplifying the progress calculation by using the
4274 * timeout as the weight. It's a good approximation for most cases, except when calling dumpsys,
4275 * where its weight should be much higher proportionally to its timeout.
4276 * Ideally, it should use a options.EstimatedDuration() instead...*/
4277 UpdateProgress(options.Timeout());
4278
4279 return status;
4280}
4281
4282void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
Rhed Jaoe017f982020-07-21 17:58:41 +08004283 const CommandOptions& options, long dumpsysTimeoutMs, int out_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004284 long timeout_ms = dumpsysTimeoutMs > 0 ? dumpsysTimeoutMs : options.TimeoutInMs();
4285 std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-T", std::to_string(timeout_ms)};
4286 dumpsys.insert(dumpsys.end(), dumpsys_args.begin(), dumpsys_args.end());
Rhed Jaoe017f982020-07-21 17:58:41 +08004287 RunCommand(title, dumpsys, options, false, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004288}
4289
Dieter Hsu105ad0c2020-09-29 15:23:33 +08004290static int open_socket(const char* service) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004291 int s = android_get_control_socket(service);
4292 if (s < 0) {
4293 MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
4294 return -1;
4295 }
4296 fcntl(s, F_SETFD, FD_CLOEXEC);
4297
4298 // Set backlog to 0 to make sure that queue size will be minimum.
4299 // In Linux, because the minimum queue will be 1, connect() will be blocked
4300 // if the other clients already called connect() and the connection request was not accepted.
4301 if (listen(s, 0) < 0) {
4302 MYLOGE("listen(control socket): %s\n", strerror(errno));
4303 return -1;
4304 }
4305
4306 struct sockaddr addr;
4307 socklen_t alen = sizeof(addr);
Abhijeet Kaur2113cae2019-09-13 09:24:15 +01004308 int fd = accept4(s, &addr, &alen, SOCK_CLOEXEC);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004309
4310 // Close socket just after accept(), to make sure that connect() by client will get error
4311 // when the socket is used by the other services.
4312 // There is still a race condition possibility between accept and close, but there is no way
4313 // to close-on-accept atomically.
4314 // See detail; b/123306389#comment25
4315 close(s);
4316
4317 if (fd < 0) {
4318 MYLOGE("accept(control socket): %s\n", strerror(errno));
4319 return -1;
4320 }
4321
4322 return fd;
4323}
4324
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004325// TODO: should call is_valid_output_file and/or be merged into it.
4326void create_parent_dirs(const char *path) {
4327 char *chp = const_cast<char *> (path);
4328
4329 /* skip initial slash */
4330 if (chp[0] == '/')
4331 chp++;
4332
4333 /* create leading directories, if necessary */
4334 struct stat dir_stat;
4335 while (chp && chp[0]) {
4336 chp = strchr(chp, '/');
4337 if (chp) {
4338 *chp = 0;
4339 if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
4340 MYLOGI("Creating directory %s\n", path);
4341 if (mkdir(path, 0770)) { /* drwxrwx--- */
4342 MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
4343 } else if (chown(path, AID_SHELL, AID_SHELL)) {
4344 MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
4345 }
4346 }
4347 *chp++ = '/';
4348 }
4349 }
4350}
4351
4352bool _redirect_to_file(FILE* redirect, char* path, int truncate_flag) {
4353 create_parent_dirs(path);
4354
4355 int fd = TEMP_FAILURE_RETRY(open(path,
4356 O_WRONLY | O_CREAT | truncate_flag | O_CLOEXEC | O_NOFOLLOW,
4357 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
4358 if (fd < 0) {
4359 MYLOGE("%s: %s\n", path, strerror(errno));
4360 return false;
4361 }
4362
4363 TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
4364 close(fd);
4365 return true;
4366}
4367
4368bool redirect_to_file(FILE* redirect, char* path) {
4369 return _redirect_to_file(redirect, path, O_TRUNC);
4370}
4371
4372bool redirect_to_existing_file(FILE* redirect, char* path) {
4373 return _redirect_to_file(redirect, path, O_APPEND);
4374}
4375
4376void dump_route_tables() {
4377 DurationReporter duration_reporter("DUMP ROUTE TABLES");
4378 if (PropertiesHelper::IsDryRun()) return;
4379 const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
4380 ds.DumpFile("RT_TABLES", RT_TABLES_PATH);
4381 FILE* fp = fopen(RT_TABLES_PATH, "re");
4382 if (!fp) {
4383 printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
4384 return;
4385 }
4386 char table[16];
4387 // Each line has an integer (the table number), a space, and a string (the table name). We only
4388 // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
4389 // Add a fixed max limit so this doesn't go awry.
4390 for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
4391 RunCommand("ROUTE TABLE IPv4", {"ip", "-4", "route", "show", "table", table});
4392 RunCommand("ROUTE TABLE IPv6", {"ip", "-6", "route", "show", "table", table});
4393 }
4394 fclose(fp);
4395}
4396
Li Li830179f2022-01-04 12:53:29 -08004397void dump_frozen_cgroupfs(const char *dir, int level,
4398 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4399 DIR *dirp;
4400 struct dirent *d;
4401 char *newpath = nullptr;
4402
4403 dirp = opendir(dir);
4404 if (dirp == nullptr) {
4405 MYLOGE("%s: %s\n", dir, strerror(errno));
4406 return;
4407 }
4408
4409 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4410 if ((d->d_name[0] == '.')
4411 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4412 || (d->d_name[1] == '\0'))) {
4413 continue;
4414 }
4415 if (d->d_type == DT_DIR) {
4416 asprintf(&newpath, "%s/%s/", dir, d->d_name);
4417 if (!newpath) {
4418 continue;
4419 }
4420 if (level == 0 && !strncmp(d->d_name, "uid_", 4)) {
4421 dump_frozen_cgroupfs(newpath, 1, dump_from_fd);
4422 } else if (level == 1 && !strncmp(d->d_name, "pid_", 4)) {
4423 char *freezer = nullptr;
4424 asprintf(&freezer, "%s/%s", newpath, "cgroup.freeze");
4425 if (freezer) {
4426 FILE* fp = fopen(freezer, "r");
4427 if (fp != NULL) {
4428 int frozen;
4429 fscanf(fp, "%d", &frozen);
4430 if (frozen > 0) {
4431 dump_files("", newpath, skip_none, dump_from_fd);
4432 }
4433 fclose(fp);
4434 }
4435 free(freezer);
4436 }
4437 }
4438 }
4439 }
4440 closedir(dirp);
4441}
4442
4443void dump_frozen_cgroupfs() {
Li Li830179f2022-01-04 12:53:29 -08004444 MYLOGD("Adding frozen processes from %s\n", CGROUPFS_DIR);
4445 DurationReporter duration_reporter("FROZEN CGROUPFS");
4446 if (PropertiesHelper::IsDryRun()) return;
4447 dump_frozen_cgroupfs(CGROUPFS_DIR, 0, _add_file_from_fd);
4448}
4449
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004450void Dumpstate::UpdateProgress(int32_t delta_sec) {
4451 if (progress_ == nullptr) {
4452 MYLOGE("UpdateProgress: progress_ not set\n");
4453 return;
4454 }
Rhed Jaobf63d8a2020-07-21 15:42:55 +08004455 // This function updates progress related members of the dumpstate and reports
4456 // progress percentage to the bugreport client. Since it could be called by
4457 // different dump tasks at the same time if the parallel run is enabled, a
4458 // mutex lock is necessary here to synchronize the call.
4459 std::lock_guard<std::recursive_mutex> lock(mutex_);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004460
4461 // Always update progess so stats can be tuned...
Nandana Dutt402a8392019-06-14 14:25:13 +01004462 progress_->Inc(delta_sec);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004463
4464 // ...but only notifiy listeners when necessary.
4465 if (!options_->do_progress_updates) return;
4466
4467 int progress = progress_->Get();
4468 int max = progress_->GetMax();
Nandana Dutt402a8392019-06-14 14:25:13 +01004469 int percent = 100 * progress / max;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004470
Nandana Dutt402a8392019-06-14 14:25:13 +01004471 if (last_reported_percent_progress_ > 0 && percent <= last_reported_percent_progress_) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004472 return;
4473 }
Nandana Dutt402a8392019-06-14 14:25:13 +01004474 last_reported_percent_progress_ = percent;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004475
4476 if (control_socket_fd_ >= 0) {
4477 dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
4478 fsync(control_socket_fd_);
4479 }
4480
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004481 if (listener_ != nullptr) {
Nandana Dutt235c6672019-11-14 15:22:32 +00004482 if (percent % 10 == 0) {
4483 // We don't want to spam logcat, so only log multiples of 10.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004484 MYLOGD("Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004485 } else {
4486 // stderr is ignored on normal invocations, but useful when calling
4487 // /system/bin/dumpstate directly for debuggging.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004488 fprintf(stderr, "Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004489 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004490
4491 listener_->onProgress(percent);
4492 }
4493}
4494
4495void Dumpstate::TakeScreenshot(const std::string& path) {
4496 const std::string& real_path = path.empty() ? screenshot_path_ : path;
4497 int status =
4498 RunCommand("", {"/system/bin/screencap", "-p", real_path},
4499 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
4500 if (status == 0) {
4501 MYLOGD("Screenshot saved on %s\n", real_path.c_str());
4502 } else {
4503 MYLOGE("Failed to take screenshot on %s\n", real_path.c_str());
4504 }
Paul Chang0d2aad72020-02-13 20:04:03 +08004505 if (listener_ != nullptr) {
4506 // Show a visual indication to indicate screenshot is taken via
4507 // IDumpstateListener.onScreenshotTaken()
4508 listener_->onScreenshotTaken(status == 0);
4509 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004510}
4511
4512bool is_dir(const char* pathname) {
4513 struct stat info;
4514 if (stat(pathname, &info) == -1) {
4515 return false;
4516 }
4517 return S_ISDIR(info.st_mode);
4518}
4519
4520time_t get_mtime(int fd, time_t default_mtime) {
4521 struct stat info;
4522 if (fstat(fd, &info) == -1) {
4523 return default_mtime;
4524 }
4525 return info.st_mtime;
4526}