blob: c24bee12be285a682f3b79f44f71e945f2fb3d85 [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
Pablo Gamito654831c2024-02-16 16:47:48 +000020#include "dumpstate.h"
Colin Crossf45fa6b2012-03-26 12:38:26 -070021
Kedar Chitnis9fd8c052021-11-16 09:09:22 +000022#include <aidl/android/hardware/dumpstate/IDumpstateDevice.h>
Felipe Leme96c2bbb2016-09-26 09:21:21 -070023#include <android-base/file.h>
24#include <android-base/properties.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070025#include <android-base/scopeguard.h>
Elliott Hughes9dc117c2015-12-07 14:21:50 -080026#include <android-base/stringprintf.h>
Naveen Kalla058e1e82016-10-19 21:38:44 -070027#include <android-base/strings.h>
Andreas Gampeaff68432016-07-18 18:01:27 -070028#include <android-base/unique_fd.h>
Kedar Chitnis9fd8c052021-11-16 09:09:22 +000029#include <android/binder_manager.h>
30#include <android/binder_process.h>
Nikita Ioffea325a572019-05-16 19:49:47 +010031#include <android/content/pm/IPackageManagerNative.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080032#include <android/hardware/dumpstate/1.0/IDumpstateDevice.h>
Hunter Knepshield8540faf2020-02-04 19:47:20 -080033#include <android/hardware/dumpstate/1.1/IDumpstateDevice.h>
34#include <android/hardware/dumpstate/1.1/types.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080035#include <android/hidl/manager/1.0/IServiceManager.h>
Nandana Duttd2f5f082019-01-18 17:13:52 +000036#include <android/os/IIncidentCompanion.h>
Pablo Gamito654831c2024-02-16 16:47:48 +000037#include <android_app_admin_flags.h>
38#include <android_tracing.h>
Nikita Ioffea325a572019-05-16 19:49:47 +010039#include <binder/IServiceManager.h>
Nikhil Kumar28ce35e2023-01-10 14:32:44 +000040#include <cutils/multiuser.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080041#include <cutils/native_handle.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070042#include <cutils/properties.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010043#include <cutils/sockets.h>
Kevin Jeon2c02e8e2022-07-07 21:45:17 +000044#include <cutils/trace.h>
Nandana Duttfaafd522019-03-11 09:23:09 +000045#include <debuggerd/client.h>
Pablo Gamito654831c2024-02-16 16:47:48 +000046#include <dirent.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080047#include <dumpsys.h>
Nandana Duttfaafd522019-03-11 09:23:09 +000048#include <dumputils/dump_utils.h>
Pablo Gamito654831c2024-02-16 16:47:48 +000049#include <errno.h>
50#include <fcntl.h>
Sahana Raof35ed432019-07-12 10:47:52 +010051#include <hardware_legacy/power.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080052#include <hidl/ServiceManagement.h>
Pablo Gamito654831c2024-02-16 16:47:48 +000053#include <inttypes.h>
54#include <libgen.h>
55#include <limits.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010056#include <log/log.h>
Tom Cherryf4472f32020-08-05 09:31:17 -070057#include <log/log_read.h>
Pablo Gamito654831c2024-02-16 16:47:48 +000058#include <math.h>
Felipe Leme75876a22016-10-27 16:31:27 -070059#include <openssl/sha.h>
Pablo Gamito654831c2024-02-16 16:47:48 +000060#include <poll.h>
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070061#include <private/android_filesystem_config.h>
62#include <private/android_logger.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080063#include <serviceutils/PriorityDumper.h>
Pablo Gamito654831c2024-02-16 16:47:48 +000064#include <signal.h>
65#include <stdarg.h>
66#include <stdbool.h>
67#include <stdio.h>
68#include <stdlib.h>
69#include <string.h>
70#include <sys/capability.h>
71#include <sys/inotify.h>
72#include <sys/klog.h>
73#include <sys/mount.h>
74#include <sys/poll.h>
75#include <sys/prctl.h>
76#include <sys/resource.h>
77#include <sys/stat.h>
78#include <sys/time.h>
79#include <sys/wait.h>
80#include <time.h>
81#include <unistd.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070082#include <utils/StrongPointer.h>
Devin Moore8df81bb2022-06-08 22:47:02 +000083#include <vintf/VintfObject.h>
Pablo Gamito654831c2024-02-16 16:47:48 +000084
85#include <chrono>
86#include <cmath>
87#include <fstream>
88#include <functional>
89#include <future>
90#include <memory>
91#include <numeric>
92#include <regex>
93#include <set>
94#include <string>
95#include <utility>
96#include <vector>
97
Felipe Lemef0292972016-11-22 13:57:05 -080098#include "DumpstateInternal.h"
Felipe Leme75876a22016-10-27 16:31:27 -070099#include "DumpstateService.h"
Felipe Leme6e01fa62015-11-11 19:35:14 -0800100
Kedar Chitnis9fd8c052021-11-16 09:09:22 +0000101namespace dumpstate_hal_hidl_1_0 = android::hardware::dumpstate::V1_0;
102namespace dumpstate_hal_hidl = android::hardware::dumpstate::V1_1;
103namespace dumpstate_hal_aidl = aidl::android::hardware::dumpstate;
104
Vishnu Naire97d6122018-01-18 13:58:56 -0800105using ::std::literals::chrono_literals::operator""ms;
106using ::std::literals::chrono_literals::operator""s;
Rhed Jao5377d792020-07-16 17:37:39 +0800107using ::std::placeholders::_1;
Steven Morelandcb7ef822016-11-29 13:20:37 -0800108
Felipe Leme47e9be22016-12-21 15:37:07 -0800109// TODO: remove once moved to namespace
Vishnu Naire97d6122018-01-18 13:58:56 -0800110using android::defaultServiceManager;
111using android::Dumpsys;
112using android::INVALID_OPERATION;
113using android::IServiceManager;
114using android::OK;
115using android::sp;
116using android::status_t;
117using android::String16;
118using android::String8;
119using android::TIMED_OUT;
120using android::UNKNOWN_ERROR;
121using android::Vector;
Nandana Dutt979388e2018-11-30 16:48:55 +0000122using android::base::StringPrintf;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000123using android::os::IDumpstateListener;
Felipe Leme47e9be22016-12-21 15:37:07 -0800124using android::os::dumpstate::CommandOptions;
125using android::os::dumpstate::DumpFileToFd;
Rhed Jao5377d792020-07-16 17:37:39 +0800126using android::os::dumpstate::DumpPool;
Vishnu Naire97d6122018-01-18 13:58:56 -0800127using android::os::dumpstate::PropertiesHelper;
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800128using android::os::dumpstate::TaskQueue;
Chris Morinbc223142022-02-04 14:17:11 -0800129using android::os::dumpstate::WaitForTask;
Felipe Leme47e9be22016-12-21 15:37:07 -0800130
Steven Moreland0d564d52025-01-10 22:24:57 +0000131// BAD - See README.md: "Dumpstate philosophy: exec not link"
132// Do not add more complicated variables here, prefer to execute only. Don't link more code here.
133
Abhijeet Kaurcf234e82019-07-01 14:53:55 +0100134// Keep in sync with
135// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
136static const int TRACE_DUMP_TIMEOUT_MS = 10000; // 10 seconds
137
138/* Most simple commands have 10 as timeout, so 5 is a good estimate */
139static const int32_t WEIGHT_FILE = 5;
140
141// TODO: temporary variables and functions used during C++ refactoring
142static Dumpstate& ds = Dumpstate::GetInstance();
143static int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Nandana Dutt8d945c02019-08-14 13:30:07 +0100144 const CommandOptions& options = CommandOptions::DEFAULT,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800145 bool verbose_duration = false, int out_fd = STDOUT_FILENO) {
146 return ds.RunCommand(title, full_command, options, verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +0100147}
148
149// Reasonable value for max stats.
150static const int STATS_MAX_N_RUNS = 1000;
151static const long STATS_MAX_AVERAGE = 100000;
152
153CommandOptions Dumpstate::DEFAULT_DUMPSYS = CommandOptions::WithTimeout(30).Build();
154
Nandana Duttd2f5f082019-01-18 17:13:52 +0000155typedef Dumpstate::ConsentCallback::ConsentResult UserConsentResult;
156
Colin Crossf45fa6b2012-03-26 12:38:26 -0700157/* read before root is shed */
158static char cmdline_buf[16384] = "(unknown)";
Yi Kong19d5c002018-07-20 13:39:55 -0700159static const char *dump_traces_path = nullptr;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000160static const uint64_t USER_CONSENT_TIMEOUT_MS = 30 * 1000;
Hunter Knepshield70610fa2020-01-03 15:27:33 -0800161// Because telephony reports are significantly faster to collect (< 10 seconds vs. > 2 minutes),
162// it's often the case that they time out far too quickly for consent with such a hefty dialog for
163// the user to read. For telephony reports only, we increase the default timeout to 2 minutes to
164// roughly match full reports' durations.
165static const uint64_t TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS = 2 * 60 * 1000;
Colin Crossf45fa6b2012-03-26 12:38:26 -0700166
Felipe Leme1d486fe2016-10-14 18:06:47 -0700167// TODO: variables and functions below should be part of dumpstate object
168
Felipe Leme635ca312016-01-05 14:23:02 -0800169static std::set<std::string> mount_points;
170void add_mountinfo();
Felipe Leme78f2c862015-12-21 09:55:22 -0800171
Todd Poynor2a83daa2013-11-22 15:44:22 -0800172#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
Mark Salyzyn7d0a7622016-06-24 14:06:15 -0700173#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
Wei Wang509bb5d2017-06-09 14:42:12 -0700174#define BLK_DEV_SYS_DIR "/sys/block"
Todd Poynor2a83daa2013-11-22 15:44:22 -0800175
Ted Bauerf6d61b82024-09-13 19:57:19 +0000176#define AFLAGS "/system/bin/aflags"
Felipe Lemee82a27d2016-01-05 13:35:44 -0800177#define RECOVERY_DIR "/cache/recovery"
Mark Salyzynd6ab0112016-03-25 12:56:39 -0700178#define RECOVERY_DATA_DIR "/data/misc/recovery"
Tianjie Xu75d53362018-04-11 16:42:28 -0700179#define UPDATE_ENGINE_LOG_DIR "/data/misc/update_engine_log"
Kelvin Zhang6eaa0f92022-09-12 09:29:19 -0700180#define UPDATE_ENGINE_PREF_DIR "/data/misc/update_engine/prefs"
Mark Salyzyn4d42dea2016-04-01 10:03:14 -0700181#define LOGPERSIST_DATA_DIR "/data/misc/logd"
Jerry Changa1df8a92020-01-02 16:03:39 +0800182#define PREREBOOT_DATA_DIR "/data/misc/prereboot"
David Brazdild2991962016-06-03 14:40:44 +0100183#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
184#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
Benedict Wong8f9d8a42019-01-03 16:19:38 -0800185#define XFRM_STAT_PROC_FILE "/proc/net/xfrm_stat"
Steven Moreland9379c462023-12-21 02:04:27 +0000186#define KERNEL_CONFIG "/proc/config.gz"
Erik Kline08165202016-05-30 11:55:44 +0900187#define WLUTIL "/vendor/xbin/wlutil"
Vishnu Nair36b4cdb2017-11-17 10:27:05 -0800188#define WMTRACE_DATA_DIR "/data/misc/wmtrace"
Yifan Hong3945e1b2019-10-29 12:59:23 -0700189#define OTA_METADATA_DIR "/metadata/ota"
Yifan Hong0efa7972020-02-03 16:45:02 -0800190#define SNAPSHOTCTL_LOG_DIR "/data/misc/snapshotctl_log"
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +0900191#define LINKERCONFIG_DIR "/linkerconfig"
Calin Juravlef84d3692020-04-28 15:31:12 -0700192#define PACKAGE_DEX_USE_LIST "/data/system/package-dex-usage.list"
Primiano Tuccifaaaafb2021-01-14 12:26:29 +0000193#define SYSTEM_TRACE_SNAPSHOT "/data/misc/perfetto-traces/bugreport/systrace.pftrace"
Li Li2eedd412021-06-30 15:11:53 -0700194#define CGROUPFS_DIR "/sys/fs/cgroup"
MÃ¥rten Kongstad60195a72022-09-20 14:14:20 +0200195#define SDK_EXT_INFO "/apex/com.android.sdkext/bin/derive_sdk"
Jeff Sharkey9df29d52023-02-06 14:26:30 -0700196#define DROPBOX_DIR "/data/system/dropbox"
MÃ¥rten Kongstad5ad813f2023-09-28 10:09:18 +0200197#define PRINT_FLAGS "/system/bin/printflags"
Nattharat Jariyanuntanaetb250cae2024-05-15 07:48:19 +0000198#define UWB_LOG_DIR "/data/misc/apexdata/com.android.uwb/log"
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700199
Narayan Kamath8f788292017-05-25 13:20:39 +0100200// TODO(narayan): Since this information has to be kept in sync
201// with tombstoned, we should just put it in a common header.
202//
203// File: system/core/debuggerd/tombstoned/tombstoned.cpp
Narayan Kamathbd863722017-06-01 18:50:12 +0100204static const std::string TOMBSTONE_DIR = "/data/tombstones/";
205static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
206static const std::string ANR_DIR = "/data/anr/";
207static const std::string ANR_FILE_PREFIX = "anr_";
Andy Hungd62f7e62024-01-11 15:47:52 -0800208static const std::string ANR_TRACE_FILE_PREFIX = "trace_";
Woody Lin20767a92022-11-29 15:50:24 +0800209static const std::string SHUTDOWN_CHECKPOINTS_DIR = "/data/system/shutdown-checkpoints/";
210static const std::string SHUTDOWN_CHECKPOINTS_FILE_PREFIX = "checkpoints-";
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700211
Felipe Lemee844a9d2016-09-21 15:01:39 -0700212// TODO: temporary variables and functions used during C++ refactoring
Nandana Dutt979388e2018-11-30 16:48:55 +0000213
Nandana Dutt5c390032019-03-12 10:52:56 +0000214#define RETURN_IF_USER_DENIED_CONSENT() \
215 if (ds.IsUserConsentDenied()) { \
216 MYLOGE("Returning early as user denied consent to share bugreport with calling app."); \
217 return Dumpstate::RunStatus::USER_CONSENT_DENIED; \
218 }
219
220// Runs func_ptr, but checks user consent before and after running it. Returns USER_CONSENT_DENIED
221// if consent is found to be denied.
222#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(func_ptr, ...) \
223 RETURN_IF_USER_DENIED_CONSENT(); \
224 func_ptr(__VA_ARGS__); \
225 RETURN_IF_USER_DENIED_CONSENT();
226
Rhed Jao5377d792020-07-16 17:37:39 +0800227// Runs func_ptr, and logs a duration report after it's finished.
228#define RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, ...) \
229 { \
230 DurationReporter duration_reporter_in_macro(log_title); \
231 func_ptr(__VA_ARGS__); \
232 }
233
234// Similar with RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK, an additional duration report
235// is output after a slow function is finished.
236#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(log_title, func_ptr, ...) \
237 RETURN_IF_USER_DENIED_CONSENT(); \
238 RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, __VA_ARGS__); \
239 RETURN_IF_USER_DENIED_CONSENT();
240
Chris Morinbc223142022-02-04 14:17:11 -0800241#define WAIT_TASK_WITH_CONSENT_CHECK(future) \
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800242 RETURN_IF_USER_DENIED_CONSENT(); \
Chris Morinbc223142022-02-04 14:17:11 -0800243 WaitForTask(future); \
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800244 RETURN_IF_USER_DENIED_CONSENT();
245
Sahana Raof35ed432019-07-12 10:47:52 +0100246static const char* WAKE_LOCK_NAME = "dumpstate_wakelock";
247
Rhed Jao5377d792020-07-16 17:37:39 +0800248// Names of parallel tasks, they are used for the DumpPool to identify the dump
249// task and the log title of the duration report.
250static const std::string DUMP_TRACES_TASK = "DUMP TRACES";
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800251static const std::string DUMP_INCIDENT_REPORT_TASK = "INCIDENT REPORT";
Aaron Huang24d215d2022-04-27 18:51:16 +0800252static const std::string DUMP_NETSTATS_PROTO_TASK = "DUMP NETSTATS PROTO";
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800253static const std::string DUMP_HALS_TASK = "DUMP HALS";
254static const std::string DUMP_BOARD_TASK = "dumpstate_board()";
Rhed Jaoe017f982020-07-21 17:58:41 +0800255static const std::string DUMP_CHECKINS_TASK = "DUMP CHECKINS";
Kean Mariottica20f2d2023-12-15 09:34:25 +0000256static const std::string SERIALIZE_PERFETTO_TRACE_TASK = "SERIALIZE PERFETTO TRACE";
Rhed Jao5377d792020-07-16 17:37:39 +0800257
Nandana Dutt979388e2018-11-30 16:48:55 +0000258namespace android {
259namespace os {
260namespace {
261
262static int Open(std::string path, int flags, mode_t mode = 0) {
263 int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
264 if (fd == -1) {
265 MYLOGE("open(%s, %s)\n", path.c_str(), strerror(errno));
266 }
267 return fd;
268}
269
mhasank2d75c442020-06-11 15:05:25 -0700270static int OpenForWrite(std::string path) {
271 return Open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
272 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
273}
Nandana Dutt979388e2018-11-30 16:48:55 +0000274
275static int OpenForRead(std::string path) {
276 return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
277}
278
279bool CopyFile(int in_fd, int out_fd) {
280 char buf[4096];
281 ssize_t byte_count;
282 while ((byte_count = TEMP_FAILURE_RETRY(read(in_fd, buf, sizeof(buf)))) > 0) {
283 if (!android::base::WriteFully(out_fd, buf, byte_count)) {
284 return false;
285 }
286 }
287 return (byte_count != -1);
288}
289
290static bool CopyFileToFd(const std::string& input_file, int out_fd) {
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000291 MYLOGD("Going to copy file (%s) to %d\n", input_file.c_str(), out_fd);
Nandana Dutt979388e2018-11-30 16:48:55 +0000292
293 // Obtain a handle to the source file.
294 android::base::unique_fd in_fd(OpenForRead(input_file));
295 if (out_fd != -1 && in_fd.get() != -1) {
296 if (CopyFile(in_fd.get(), out_fd)) {
297 return true;
298 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000299 MYLOGE("Failed to copy file: %s\n", strerror(errno));
Nandana Dutt979388e2018-11-30 16:48:55 +0000300 }
301 return false;
302}
303
Nandana Duttd2f5f082019-01-18 17:13:52 +0000304static bool UnlinkAndLogOnError(const std::string& file) {
Nandana Dutt8ae16e62020-03-27 10:20:22 +0000305 if (file.empty()) {
306 return false;
307 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000308 if (unlink(file.c_str())) {
309 MYLOGE("Failed to unlink file (%s): %s\n", file.c_str(), strerror(errno));
Nandana Duttd2f5f082019-01-18 17:13:52 +0000310 return false;
311 }
312 return true;
313}
Nandana Dutt979388e2018-11-30 16:48:55 +0000314
Nikita Ioffea325a572019-05-16 19:49:47 +0100315int64_t GetModuleMetadataVersion() {
316 auto binder = defaultServiceManager()->getService(android::String16("package_native"));
317 if (binder == nullptr) {
318 MYLOGE("Failed to retrieve package_native service");
319 return 0L;
320 }
321 auto package_service = android::interface_cast<content::pm::IPackageManagerNative>(binder);
322 std::string package_name;
323 auto status = package_service->getModuleMetadataPackageName(&package_name);
324 if (!status.isOk()) {
325 MYLOGE("Failed to retrieve module metadata package name: %s", status.toString8().c_str());
326 return 0L;
327 }
Nandana Duttdb379fa2019-10-09 16:54:41 +0100328 MYLOGD("Module metadata package name: %s\n", package_name.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100329 int64_t version_code;
330 status = package_service->getVersionCodeForPackage(android::String16(package_name.c_str()),
331 &version_code);
332 if (!status.isOk()) {
333 MYLOGE("Failed to retrieve module metadata version: %s", status.toString8().c_str());
334 return 0L;
335 }
336 return version_code;
337}
338
mhasank2d75c442020-06-11 15:05:25 -0700339static bool PathExists(const std::string& path) {
340 struct stat sb;
341 return stat(path.c_str(), &sb) == 0;
342}
343
344static bool CopyFileToFile(const std::string& input_file, const std::string& output_file) {
345 if (input_file == output_file) {
346 MYLOGD("Skipping copying bugreport file since the destination is the same (%s)\n",
347 output_file.c_str());
348 return false;
349 }
350 else if (PathExists(output_file)) {
351 MYLOGD("Cannot overwrite an existing file (%s)\n", output_file.c_str());
352 return false;
353 }
354
355 MYLOGD("Going to copy bugreport file (%s) to %s\n", input_file.c_str(), output_file.c_str());
356 android::base::unique_fd out_fd(OpenForWrite(output_file));
357 return CopyFileToFd(input_file, out_fd.get());
358}
359
Nandana Dutt979388e2018-11-30 16:48:55 +0000360} // namespace
361} // namespace os
362} // namespace android
363
Felipe Leme678727a2016-09-21 17:22:11 -0700364static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
Felipe Lemebda15a02016-11-16 17:48:25 -0800365 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
Rhed Jaoe017f982020-07-21 17:58:41 +0800366 long dumpsysTimeoutMs = 0, int out_fd = STDOUT_FILENO) {
367 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs, out_fd);
368}
369static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
370 int out_fd) {
371 return ds.RunDumpsys(title, dumpsysArgs, Dumpstate::DEFAULT_DUMPSYS, 0, out_fd);
Felipe Leme678727a2016-09-21 17:22:11 -0700372}
373static int DumpFile(const std::string& title, const std::string& path) {
374 return ds.DumpFile(title, path);
375}
Felipe Lemee82a27d2016-01-05 13:35:44 -0800376
Felipe Lemee844a9d2016-09-21 15:01:39 -0700377// Relative directory (inside the zip) for all files copied as-is into the bugreport.
378static const std::string ZIP_ROOT_DIR = "FS";
379
Vishnu Naire97d6122018-01-18 13:58:56 -0800380static const std::string kProtoPath = "proto/";
381static const std::string kProtoExt = ".proto";
Jie Song9fbfad02017-06-20 16:29:42 -0700382static const std::string kDumpstateBoardFiles[] = {
383 "dumpstate_board.txt",
Felipe Leme95d6ca52017-08-01 16:35:56 -0700384 "dumpstate_board.bin"
Jie Song9fbfad02017-06-20 16:29:42 -0700385};
386static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
387
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700388static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Lemed071c682016-10-20 16:48:00 -0700389static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700390
Felipe Lemef0292972016-11-22 13:57:05 -0800391static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
392
Narayan Kamath8f788292017-05-25 13:20:39 +0100393/*
Narayan Kamathbd863722017-06-01 18:50:12 +0100394 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
Rhed Jao01dc0c62020-06-03 17:13:30 +0800395 * The returned vector is sorted by the mtimes of the dumps with descending
Chris Morinc2cba7a2022-02-01 17:06:50 -0800396 * order.
Narayan Kamath8f788292017-05-25 13:20:39 +0100397 */
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700398static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
Chris Morinc2cba7a2022-02-01 17:06:50 -0800399 const std::string& file_prefix) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100400 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100401
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700402 if (dump_dir == nullptr) {
403 MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno));
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700404 return std::vector<DumpData>();
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700405 }
406
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700407 std::vector<DumpData> dump_data;
Narayan Kamathbd863722017-06-01 18:50:12 +0100408 struct dirent* entry = nullptr;
409 while ((entry = readdir(dump_dir.get()))) {
410 if (entry->d_type != DT_REG) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100411 continue;
412 }
413
Narayan Kamathbd863722017-06-01 18:50:12 +0100414 const std::string base_name(entry->d_name);
415 if (base_name.find(file_prefix) != 0) {
416 continue;
417 }
418
419 const std::string abs_path = dir_path + base_name;
420 android::base::unique_fd fd(
421 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
422 if (fd == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700423 MYLOGW("Unable to open dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamathbd863722017-06-01 18:50:12 +0100424 break;
425 }
426
427 struct stat st = {};
428 if (fstat(fd, &st) == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700429 MYLOGW("Unable to stat dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamath8f788292017-05-25 13:20:39 +0100430 continue;
431 }
432
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700433 dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700434 }
Rhed Jao01dc0c62020-06-03 17:13:30 +0800435 if (!dump_data.empty()) {
436 std::sort(dump_data.begin(), dump_data.end(),
437 [](const auto& a, const auto& b) { return a.mtime > b.mtime; });
438 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100439
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700440 return dump_data;
Narayan Kamath8f788292017-05-25 13:20:39 +0100441}
442
Narayan Kamathbd863722017-06-01 18:50:12 +0100443static bool AddDumps(const std::vector<DumpData>::const_iterator start,
444 const std::vector<DumpData>::const_iterator end,
445 const char* type_name, const bool add_to_zip) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100446 bool dumped = false;
Narayan Kamathbd863722017-06-01 18:50:12 +0100447 for (auto it = start; it != end; ++it) {
448 const std::string& name = it->name;
449 const int fd = it->fd;
Narayan Kamath8f788292017-05-25 13:20:39 +0100450 dumped = true;
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100451
452 // Seek to the beginning of the file before dumping any data. A given
453 // DumpData entry might be dumped multiple times in the report.
454 //
455 // For example, the most recent ANR entry is dumped to the body of the
456 // main entry and it also shows up as a separate entry in the bugreport
457 // ZIP file.
458 if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) {
459 MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(),
460 strerror(errno));
461 }
462
Chris Morinc2cba7a2022-02-01 17:06:50 -0800463 if (add_to_zip) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800464 if (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd, /* timeout = */ 0ms) != OK) {
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100465 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100466 }
467 } else {
468 dump_file_from_fd(type_name, name.c_str(), fd);
469 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100470 }
471
472 return dumped;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700473}
474
Felipe Leme635ca312016-01-05 14:23:02 -0800475// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700476void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800477 char path[PATH_MAX];
478
479 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
480 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700481 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800482 char linkname[PATH_MAX];
483 ssize_t r = readlink(path, linkname, PATH_MAX);
484 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800485 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800486 return;
487 }
488 linkname[r] = '\0';
489
490 if (mount_points.find(linkname) == mount_points.end()) {
491 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700492 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700493 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
Felipe Leme635ca312016-01-05 14:23:02 -0800494 mount_points.insert(linkname);
495 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800496 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800497 }
498 }
499}
500
501void add_mountinfo() {
Felipe Leme678727a2016-09-21 17:22:11 -0700502 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800503 mount_points.clear();
Felipe Leme46b85da2016-11-21 17:40:45 -0800504 DurationReporter duration_reporter(title, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700505 for_each_pid(do_mountinfo, nullptr);
506 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800507}
508
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700509static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
510{
511 DIR *d;
512 struct dirent *de;
513 char path[PATH_MAX];
514
515 d = opendir(driverpath);
Yi Kong19d5c002018-07-20 13:39:55 -0700516 if (d == nullptr) {
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700517 return;
518 }
519
520 while ((de = readdir(d))) {
521 if (de->d_type != DT_LNK) {
522 continue;
523 }
524 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700525 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700526 }
527
528 closedir(d);
529}
530
Mark Salyzyn326842f2015-04-30 09:49:41 -0700531static bool skip_not_stat(const char *path) {
532 static const char stat[] = "/stat";
533 size_t len = strlen(path);
534 if (path[len - 1] == '/') { /* Directory? */
535 return false;
536 }
537 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
538}
539
Jeff Sharkey9df29d52023-02-06 14:26:30 -0700540static bool skip_wtf_strictmode(const char *path) {
541 if (strstr(path, "_wtf")) {
542 return true;
543 } else if (strstr(path, "_strictmode")) {
544 return true;
545 }
546 return false;
547}
548
Felipe Leme4c2d6632016-09-28 14:32:00 -0700549static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800550 return false;
551}
552
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700553unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700554
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800555//
556// stat offsets
557// Name units description
558// ---- ----- -----------
559// read I/Os requests number of read I/Os processed
560#define __STAT_READ_IOS 0
561// read merges requests number of read I/Os merged with in-queue I/O
562#define __STAT_READ_MERGES 1
563// read sectors sectors number of sectors read
564#define __STAT_READ_SECTORS 2
565// read ticks milliseconds total wait time for read requests
566#define __STAT_READ_TICKS 3
567// write I/Os requests number of write I/Os processed
568#define __STAT_WRITE_IOS 4
569// write merges requests number of write I/Os merged with in-queue I/O
570#define __STAT_WRITE_MERGES 5
571// write sectors sectors number of sectors written
572#define __STAT_WRITE_SECTORS 6
573// write ticks milliseconds total wait time for write requests
574#define __STAT_WRITE_TICKS 7
575// in_flight requests number of I/Os currently in flight
576#define __STAT_IN_FLIGHT 8
577// io_ticks milliseconds total time this block device has been active
578#define __STAT_IO_TICKS 9
579// time_in_queue milliseconds total wait time for all requests
580#define __STAT_IN_QUEUE 10
581#define __STAT_NUMBER_FIELD 11
582//
583// read I/Os, write I/Os
584// =====================
585//
586// These values increment when an I/O request completes.
587//
588// read merges, write merges
589// =========================
590//
591// These values increment when an I/O request is merged with an
592// already-queued I/O request.
593//
594// read sectors, write sectors
595// ===========================
596//
597// These values count the number of sectors read from or written to this
598// block device. The "sectors" in question are the standard UNIX 512-byte
599// sectors, not any device- or filesystem-specific block size. The
600// counters are incremented when the I/O completes.
601#define SECTOR_SIZE 512
602//
603// read ticks, write ticks
604// =======================
605//
606// These values count the number of milliseconds that I/O requests have
607// waited on this block device. If there are multiple I/O requests waiting,
608// these values will increase at a rate greater than 1000/second; for
609// example, if 60 read requests wait for an average of 30 ms, the read_ticks
610// field will increase by 60*30 = 1800.
611//
612// in_flight
613// =========
614//
615// This value counts the number of I/O requests that have been issued to
616// the device driver but have not yet completed. It does not include I/O
617// requests that are in the queue but not yet issued to the device driver.
618//
619// io_ticks
620// ========
621//
622// This value counts the number of milliseconds during which the device has
623// had I/O requests queued.
624//
625// time_in_queue
626// =============
627//
628// This value counts the number of milliseconds that I/O requests have waited
629// on this block device. If there are multiple I/O requests waiting, this
630// value will increase as the product of the number of milliseconds times the
631// number of requests waiting (see "read ticks" above for an example).
632#define S_TO_MS 1000
633//
634
Mark Salyzyn326842f2015-04-30 09:49:41 -0700635static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800636 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700637 bool z;
Yi Kong19d5c002018-07-20 13:39:55 -0700638 char *cp, *buffer = nullptr;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700639 size_t i = 0;
Josh Gao7c4258c2018-06-25 13:40:08 -0700640 FILE *fp = fdopen(dup(fd), "rb");
Mark Salyzyn326842f2015-04-30 09:49:41 -0700641 getline(&buffer, &i, fp);
642 fclose(fp);
643 if (!buffer) {
644 return -errno;
645 }
646 i = strlen(buffer);
647 while ((i > 0) && (buffer[i - 1] == '\n')) {
648 buffer[--i] = '\0';
649 }
650 if (!*buffer) {
651 free(buffer);
652 return 0;
653 }
654 z = true;
655 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800656 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700657 if (fields[i] != 0) {
658 z = false;
659 }
660 }
661 if (z) { /* never accessed */
662 free(buffer);
663 return 0;
664 }
665
Wei Wang509bb5d2017-06-09 14:42:12 -0700666 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
667 path += sizeof(BLK_DEV_SYS_DIR) - 1;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700668 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700669
670 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
671 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
672 "W-wait", "in-fli", "activ", "T-wait", path, buffer);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700673 free(buffer);
674
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800675 if (fields[__STAT_IO_TICKS]) {
676 unsigned long read_perf = 0;
677 unsigned long read_ios = 0;
678 if (fields[__STAT_READ_TICKS]) {
679 unsigned long long divisor = fields[__STAT_READ_TICKS]
680 * fields[__STAT_IO_TICKS];
681 read_perf = ((unsigned long long)SECTOR_SIZE
682 * fields[__STAT_READ_SECTORS]
683 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
684 / divisor;
685 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
686 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
687 / divisor;
688 }
689
690 unsigned long write_perf = 0;
691 unsigned long write_ios = 0;
692 if (fields[__STAT_WRITE_TICKS]) {
693 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
694 * fields[__STAT_IO_TICKS];
695 write_perf = ((unsigned long long)SECTOR_SIZE
696 * fields[__STAT_WRITE_SECTORS]
697 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
698 / divisor;
699 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
700 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
701 / divisor;
702 }
703
704 unsigned queue = (fields[__STAT_IN_QUEUE]
705 + (fields[__STAT_IO_TICKS] >> 1))
706 / fields[__STAT_IO_TICKS];
707
708 if (!write_perf && !write_ios) {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700709 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 -0800710 } else {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700711 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 -0800712 read_ios, write_perf, write_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800713 }
714
715 /* bugreport timeout factor adjustment */
716 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
717 worst_write_perf = write_perf;
718 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700719 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700720 return 0;
721}
722
Yao Chenbe3bbc12018-01-17 16:31:10 -0800723static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
724
Tom Cherryf4472f32020-08-05 09:31:17 -0700725// Returns the actual readable size of the given buffer or -1 on error.
726static long logcat_buffer_readable_size(const std::string& buffer) {
727 std::unique_ptr<logger_list, decltype(&android_logger_list_free)> logger_list{
728 android_logger_list_alloc(0, 0, 0), &android_logger_list_free};
729 auto logger = android_logger_open(logger_list.get(), android_name_to_log_id(buffer.c_str()));
730
731 return android_logger_get_log_readable_size(logger);
732}
733
734// Returns timeout in ms to read a list of buffers.
Yao Chenbe3bbc12018-01-17 16:31:10 -0800735static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
736 unsigned long timeout_ms = 0;
737 for (const auto& buffer : buffers) {
Tom Cherryf4472f32020-08-05 09:31:17 -0700738 long readable_size = logcat_buffer_readable_size(buffer);
739 if (readable_size > 0) {
740 // Engineering margin is ten-fold our guess.
741 timeout_ms += 10 * (readable_size + worst_write_perf) / worst_write_perf;
742 }
Yao Chenbe3bbc12018-01-17 16:31:10 -0800743 }
744 return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700745}
746
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800747// Opens a socket and returns its file descriptor.
748static int open_socket(const char* service);
749
Nandana Duttd2f5f082019-01-18 17:13:52 +0000750Dumpstate::ConsentCallback::ConsentCallback() : result_(UNAVAILABLE), start_time_(Nanotime()) {
751}
752
753android::binder::Status Dumpstate::ConsentCallback::onReportApproved() {
754 std::lock_guard<std::mutex> lock(lock_);
755 result_ = APPROVED;
756 MYLOGD("User approved consent to share bugreport\n");
Paul Chang0d2aad72020-02-13 20:04:03 +0800757
758 // Maybe copy screenshot so calling app can display the screenshot to the user as soon as
759 // consent is granted.
760 if (ds.options_->is_screenshot_copied) {
761 return android::binder::Status::ok();
762 }
763
764 if (!ds.options_->do_screenshot || ds.options_->screenshot_fd.get() == -1 ||
765 !ds.do_early_screenshot_) {
766 return android::binder::Status::ok();
767 }
768
769 bool copy_succeeded = android::os::CopyFileToFd(ds.screenshot_path_,
770 ds.options_->screenshot_fd.get());
771 ds.options_->is_screenshot_copied = copy_succeeded;
772 if (copy_succeeded) {
773 android::os::UnlinkAndLogOnError(ds.screenshot_path_);
774 }
Nandana Duttd2f5f082019-01-18 17:13:52 +0000775 return android::binder::Status::ok();
776}
777
778android::binder::Status Dumpstate::ConsentCallback::onReportDenied() {
779 std::lock_guard<std::mutex> lock(lock_);
780 result_ = DENIED;
781 MYLOGW("User denied consent to share bugreport\n");
782 return android::binder::Status::ok();
783}
784
785UserConsentResult Dumpstate::ConsentCallback::getResult() {
786 std::lock_guard<std::mutex> lock(lock_);
787 return result_;
788}
789
790uint64_t Dumpstate::ConsentCallback::getElapsedTimeMs() const {
Hunter Knepshieldf0a39052020-01-03 14:53:04 -0800791 return (Nanotime() - start_time_) / NANOS_PER_MILLI;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000792}
793
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700794void Dumpstate::PrintHeader() const {
MÃ¥rten Kongstad60195a72022-09-20 14:14:20 +0200795 std::string build, fingerprint, radio, bootloader, network, sdkversion;
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700796 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700797
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700798 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
799 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700800 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
801 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
802 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
MÃ¥rten Kongstad60195a72022-09-20 14:14:20 +0200803 sdkversion = android::base::GetProperty("ro.build.version.sdk", "(unknown)");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700804 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
Colin Crossf45fa6b2012-03-26 12:38:26 -0700805
Felipe Lemed8b94e52016-12-08 10:21:44 -0800806 printf("========================================================\n");
807 printf("== dumpstate: %s\n", date);
808 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700809
Felipe Lemed8b94e52016-12-08 10:21:44 -0800810 printf("\n");
811 printf("Build: %s\n", build.c_str());
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700812 // NOTE: fingerprint entry format is important for other tools.
Felipe Lemed8b94e52016-12-08 10:21:44 -0800813 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
814 printf("Bootloader: %s\n", bootloader.c_str());
815 printf("Radio: %s\n", radio.c_str());
816 printf("Network: %s\n", network.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100817 int64_t module_metadata_version = android::os::GetModuleMetadataVersion();
818 if (module_metadata_version != 0) {
819 printf("Module Metadata version: %" PRId64 "\n", module_metadata_version);
820 }
MÃ¥rten Kongstad60195a72022-09-20 14:14:20 +0200821 printf("Android SDK version: %s\n", sdkversion.c_str());
822 printf("SDK extensions: ");
823 RunCommandToFd(STDOUT_FILENO, "", {SDK_EXT_INFO, "--header"},
824 CommandOptions::WithTimeout(1).Always().DropRoot().Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700825
Felipe Lemed8b94e52016-12-08 10:21:44 -0800826 printf("Kernel: ");
Felipe Lemef0292972016-11-22 13:57:05 -0800827 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
Felipe Lemed8b94e52016-12-08 10:21:44 -0800828 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
Devin Moore09fde8d2023-03-21 16:28:22 +0000829 printf("Bootconfig: ");
830 DumpFileToFd(STDOUT_FILENO, "", "/proc/bootconfig");
Felipe Leme7709f8a2017-12-05 09:30:09 -0800831 printf("Uptime: ");
832 RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"},
833 CommandOptions::WithTimeout(1).Always().Build());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800834 printf("Bugreport format version: %s\n", version_.c_str());
Kevin Jeonfa64e642023-07-27 11:36:41 -0400835 printf(
836 "Dumpstate info: id=%d pid=%d dry_run=%d parallel_run=%d strict_run=%d args=%s "
837 "bugreport_mode=%s\n",
838 id_, pid_, PropertiesHelper::IsDryRun(), PropertiesHelper::IsParallelRun(),
839 PropertiesHelper::IsStrictRun(), options_->args.c_str(),
840 options_->bugreport_mode_string.c_str());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800841 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800842}
843
Felipe Leme24b66ee2016-06-16 10:55:26 -0700844// List of file extensions that can cause a zip file attachment to be rejected by some email
845// service providers.
846static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
847 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
848 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
849 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
850};
851
Vishnu Naire97d6122018-01-18 13:58:56 -0800852status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd,
853 std::chrono::milliseconds timeout = 0ms) {
Felipe Leme24b66ee2016-06-16 10:55:26 -0700854 std::string valid_name = entry_name;
855
856 // Rename extension if necessary.
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -0700857 size_t idx = entry_name.rfind('.');
Felipe Leme24b66ee2016-06-16 10:55:26 -0700858 if (idx != std::string::npos) {
859 std::string extension = entry_name.substr(idx);
860 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
861 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
862 valid_name = entry_name + ".renamed";
863 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
864 }
865 }
866
Felipe Leme6fe9db62016-02-12 09:04:16 -0800867 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
868 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Kevin Jeon9bbe0ac2022-05-05 22:05:43 +0000869 size_t flags = ZipWriter::kCompress | ZipWriter::kDefaultCompression;
870 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), flags,
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700871 get_mtime(fd, ds.now_));
Felipe Leme1d486fe2016-10-14 18:06:47 -0700872 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700873 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700874 ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800875 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800876 }
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000877 bool finished_entry = false;
878 auto finish_entry = [this, &finished_entry] {
879 if (!finished_entry) {
880 // This should only be called when we're going to return an earlier error,
881 // which would've been logged. This may imply the file is already corrupt
882 // and any further logging from FinishEntry is more likely to mislead than
883 // not.
884 this->zip_writer_->FinishEntry();
885 }
886 };
887 auto scope_guard = android::base::make_scope_guard(finish_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -0800888 auto start = std::chrono::steady_clock::now();
889 auto end = start + timeout;
890 struct pollfd pfd = {fd, POLLIN};
Felipe Lemee82a27d2016-01-05 13:35:44 -0800891
Felipe Leme770410d2016-01-26 17:07:14 -0800892 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800893 while (1) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800894 if (timeout.count() > 0) {
895 // lambda to recalculate the timeout.
896 auto time_left_ms = [end]() {
897 auto now = std::chrono::steady_clock::now();
898 auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
899 return std::max(diff.count(), 0LL);
900 };
901
902 int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
903 if (rc < 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000904 MYLOGE("Error in poll while adding from fd to zip entry %s:%s\n",
905 entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800906 return -errno;
907 } else if (rc == 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000908 MYLOGE("Timed out adding from fd to zip entry %s:%s Timeout:%lldms\n",
Vishnu Naire97d6122018-01-18 13:58:56 -0800909 entry_name.c_str(), strerror(errno), timeout.count());
910 return TIMED_OUT;
911 }
912 }
913
Zach Riggle22200402016-08-18 01:01:24 -0400914 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800915 if (bytes_read == 0) {
916 break;
917 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800918 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800919 return -errno;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800920 }
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700921 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800922 if (err) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700923 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800924 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800925 }
926 }
927
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700928 err = zip_writer_->FinishEntry();
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000929 finished_entry = true;
Felipe Leme1d486fe2016-10-14 18:06:47 -0700930 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700931 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800932 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800933 }
934
Vishnu Naire97d6122018-01-18 13:58:56 -0800935 return OK;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800936}
937
Felipe Leme1d486fe2016-10-14 18:06:47 -0700938bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
939 android::base::unique_fd fd(
940 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700941 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800942 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800943 return false;
944 }
945
Vishnu Naire97d6122018-01-18 13:58:56 -0800946 return (AddZipEntryFromFd(entry_name, fd.get()) == OK);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800947}
948
949/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700950static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800951 return (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) == OK) ? 0 : 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800952}
953
Felipe Leme1d486fe2016-10-14 18:06:47 -0700954void Dumpstate::AddDir(const std::string& dir, bool recursive) {
Felipe Leme678727a2016-09-21 17:22:11 -0700955 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
Felipe Leme46b85da2016-11-21 17:40:45 -0800956 DurationReporter duration_reporter(dir, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700957 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800958}
959
Felipe Leme1d486fe2016-10-14 18:06:47 -0700960bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800961 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Kevin Jeon9bbe0ac2022-05-05 22:05:43 +0000962 size_t flags = ZipWriter::kCompress | ZipWriter::kDefaultCompression;
963 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), flags, ds.now_);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700964 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700965 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700966 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800967 return false;
968 }
969
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700970 err = zip_writer_->WriteBytes(content.c_str(), content.length());
Felipe Leme1d486fe2016-10-14 18:06:47 -0700971 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700972 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700973 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800974 return false;
975 }
976
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700977 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700978 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700979 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800980 return false;
981 }
982
983 return true;
984}
985
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800986static void DoKmsg() {
987 struct stat st;
988 if (!stat(PSTORE_LAST_KMSG, &st)) {
989 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
990 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
991 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
992 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
993 } else {
994 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
995 DumpFile("LAST KMSG", "/proc/last_kmsg");
996 }
997}
998
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800999static void DoKernelLogcat() {
Yao Chenbe3bbc12018-01-17 16:31:10 -08001000 unsigned long timeout_ms = logcat_timeout({"kernel"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001001 RunCommand(
1002 "KERNEL LOG",
1003 {"logcat", "-b", "kernel", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1004 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1005}
1006
Nandana Duttdb379fa2019-10-09 16:54:41 +01001007static void DoSystemLogcat(time_t since) {
1008 char since_str[80];
1009 strftime(since_str, sizeof(since_str), "%Y-%m-%d %H:%M:%S.000", localtime(&since));
1010
1011 unsigned long timeout_ms = logcat_timeout({"main", "system", "crash"});
1012 RunCommand("SYSTEM LOG",
1013 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v", "-T",
1014 since_str},
1015 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1016}
1017
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001018static void DoRadioLogcat() {
1019 unsigned long timeout_ms = logcat_timeout({"radio"});
1020 RunCommand(
1021 "RADIO LOG",
1022 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1023 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
1024}
1025
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001026static void DoLogcat() {
Vishnu Nair6921f802017-11-22 09:17:23 -08001027 unsigned long timeout_ms;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001028 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
1029 // calculate timeout
Yao Chenbe3bbc12018-01-17 16:31:10 -08001030 timeout_ms = logcat_timeout({"main", "system", "crash"});
Tony Makae737652017-03-30 17:47:09 +01001031 RunCommand("SYSTEM LOG",
Vishnu Nair6921f802017-11-22 09:17:23 -08001032 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1033 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -08001034 timeout_ms = logcat_timeout({"events"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001035 RunCommand(
1036 "EVENT LOG",
1037 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001038 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Yao Chenbe3bbc12018-01-17 16:31:10 -08001039 timeout_ms = logcat_timeout({"stats"});
1040 RunCommand(
1041 "STATS LOG",
1042 {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001043 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001044 DoRadioLogcat();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001045
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001046 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001047 RunCommand("LAST LOGCAT", {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable",
1048 "-v", "uid", "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001049}
1050
Mike Ma5c267872019-08-21 11:31:34 -07001051static void DumpIncidentReport() {
Mike Ma5c267872019-08-21 11:31:34 -07001052 const std::string path = ds.bugreport_internal_dir_ + "/tmp_incident_report";
1053 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1054 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1055 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1056 if (fd < 0) {
1057 MYLOGE("Could not open %s to dump incident report.\n", path.c_str());
1058 return;
1059 }
Kevin Jeonfa64e642023-07-27 11:36:41 -04001060 RunCommandToFd(fd, "", {"incident", "-u"},
1061 CommandOptions::WithTimeout(PropertiesHelper::IsStrictRun() ? 20 : 120).Build());
Mike Ma5c267872019-08-21 11:31:34 -07001062 bool empty = 0 == lseek(fd, 0, SEEK_END);
1063 if (!empty) {
1064 // Use a different name from "incident.proto"
1065 // /proto/incident.proto is reserved for incident service dump
1066 // i.e. metadata for debugging.
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001067 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "incident_report" + kProtoExt,
1068 path);
1069 } else {
1070 unlink(path.c_str());
Mike Ma5c267872019-08-21 11:31:34 -07001071 }
Mike Ma5c267872019-08-21 11:31:34 -07001072}
1073
Aaron Huang24d215d2022-04-27 18:51:16 +08001074static void DumpNetstatsProto() {
1075 const std::string path = ds.bugreport_internal_dir_ + "/tmp_netstats_proto";
1076 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1077 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1078 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1079 if (fd < 0) {
1080 MYLOGE("Could not open %s to dump netstats proto.\n", path.c_str());
1081 return;
1082 }
1083 RunCommandToFd(fd, "", {"dumpsys", "netstats", "--proto"},
Kevin Jeon2fb3dd62022-09-28 18:48:55 +00001084 CommandOptions::WithTimeout(5).Build());
Aaron Huang24d215d2022-04-27 18:51:16 +08001085 bool empty = 0 == lseek(fd, 0, SEEK_END);
1086 if (!empty) {
1087 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "netstats" + kProtoExt,
1088 path);
1089 } else {
1090 unlink(path.c_str());
1091 }
1092}
1093
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001094static void MaybeAddSystemTraceToZip() {
1095 // This function copies into the .zip the system trace that was snapshotted
Kean Mariottica20f2d2023-12-15 09:34:25 +00001096 // by the early call to MaybeSnapshotSystemTraceAsync(), if any background
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001097 // tracing was happening.
Kean Mariotti853b73a2023-07-27 12:40:30 +00001098 bool system_trace_exists = access(SYSTEM_TRACE_SNAPSHOT, F_OK) == 0;
1099 if (!system_trace_exists) {
Kean Mariottica20f2d2023-12-15 09:34:25 +00001100 // No background trace was happening at the time MaybeSnapshotSystemTraceAsync() was invoked
Kean Mariotti853b73a2023-07-27 12:40:30 +00001101 if (!PropertiesHelper::IsUserBuild()) {
1102 MYLOGI(
1103 "No system traces found. Check for previously uploaded traces by looking for "
1104 "go/trace-uuid in logcat")
1105 }
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001106 return;
1107 }
1108 ds.AddZipEntry(
1109 ZIP_ROOT_DIR + SYSTEM_TRACE_SNAPSHOT,
1110 SYSTEM_TRACE_SNAPSHOT);
1111 android::os::UnlinkAndLogOnError(SYSTEM_TRACE_SNAPSHOT);
1112}
1113
Sunny Goyal35949782019-11-19 15:54:36 -08001114static void DumpVisibleWindowViews() {
Sunny Goyal35949782019-11-19 15:54:36 -08001115 DurationReporter duration_reporter("VISIBLE WINDOW VIEWS");
1116 const std::string path = ds.bugreport_internal_dir_ + "/tmp_visible_window_views";
1117 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1118 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1119 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1120 if (fd < 0) {
1121 MYLOGE("Could not open %s to dump visible views.\n", path.c_str());
1122 return;
1123 }
1124 RunCommandToFd(fd, "", {"cmd", "window", "dump-visible-window-views"},
Kevin Jeon774abde2022-09-28 18:20:43 +00001125 CommandOptions::WithTimeout(10).Build());
Sunny Goyal35949782019-11-19 15:54:36 -08001126 bool empty = 0 == lseek(fd, 0, SEEK_END);
1127 if (!empty) {
1128 ds.AddZipEntry("visible_windows.zip", path);
1129 } else {
1130 MYLOGW("Failed to dump visible windows\n");
1131 }
1132 unlink(path.c_str());
1133}
1134
Jayachandran Ca94c7172017-06-10 15:08:12 -07001135static void DumpIpTablesAsRoot() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001136 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
1137 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +09001138 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001139 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +09001140 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
1141 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
1142 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
1143 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001144}
1145
Woody Lin20767a92022-11-29 15:50:24 +08001146static void DumpShutdownCheckpoints() {
1147 const bool shutdown_checkpoints_dumped = AddDumps(
1148 ds.shutdown_checkpoints_.begin(), ds.shutdown_checkpoints_.end(),
1149 "SHUTDOWN CHECKPOINTS", false /* add_to_zip */);
1150 if (!shutdown_checkpoints_dumped) {
1151 printf("*** NO SHUTDOWN CHECKPOINTS to dump in %s\n\n",
1152 SHUTDOWN_CHECKPOINTS_DIR.c_str());
1153 }
1154}
1155
David Andersond9ba4752018-12-11 18:26:59 -08001156static void DumpDynamicPartitionInfo() {
1157 if (!::android::base::GetBoolProperty("ro.boot.dynamic_partitions", false)) {
1158 return;
1159 }
1160
1161 RunCommand("LPDUMP", {"lpdump", "--all"});
David Anderson6650ade2019-10-02 15:18:59 -07001162 RunCommand("DEVICE-MAPPER", {"gsid", "dump-device-mapper"});
David Andersond9ba4752018-12-11 18:26:59 -08001163}
1164
Chris Morin5a50d482022-02-01 17:41:18 -08001165static void AddAnrTraceDir(const std::string& anr_traces_dir) {
Narayan Kamath8f788292017-05-25 13:20:39 +01001166 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
1167 anr_traces_dir.c_str());
1168
1169 // If we're here, dump_traces_path will always be a temporary file
1170 // (created with mkostemp or similar) that contains dumps taken earlier
1171 // on in the process.
1172 if (dump_traces_path != nullptr) {
Chris Morin5a50d482022-02-01 17:41:18 -08001173 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
1174 dump_traces_path);
1175 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
Narayan Kamath8f788292017-05-25 13:20:39 +01001176
1177 const int ret = unlink(dump_traces_path);
1178 if (ret == -1) {
1179 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
1180 strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -07001181 }
1182 }
1183
Narayan Kamathbd863722017-06-01 18:50:12 +01001184 // Add a specific message for the first ANR Dump.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001185 if (ds.anr_data_.size() > 0) {
Chris Morin5a50d482022-02-01 17:41:18 -08001186 // The "last" ANR will always be present in the body of the main entry.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001187 AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1,
Chris Morin5a50d482022-02-01 17:41:18 -08001188 "VM TRACES AT LAST ANR", false /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001189
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001190 // Historical ANRs are always included as separate entries in the bugreport zip file.
Chris Morin5a50d482022-02-01 17:41:18 -08001191 AddDumps(ds.anr_data_.begin(), ds.anr_data_.end(),
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001192 "HISTORICAL ANR", true /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001193 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +01001194 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
1195 }
Andy Hungd62f7e62024-01-11 15:47:52 -08001196
1197 // Add Java anr traces (such as generated by the Finalizer Watchdog).
1198 AddDumps(ds.anr_trace_data_.begin(), ds.anr_trace_data_.end(), "JAVA ANR TRACES",
1199 true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001200}
1201
1202static void AddAnrTraceFiles() {
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001203 std::string anr_traces_dir = "/data/anr";
Narayan Kamath8f788292017-05-25 13:20:39 +01001204
Chris Morin5a50d482022-02-01 17:41:18 -08001205 AddAnrTraceDir(anr_traces_dir);
Narayan Kamath8f788292017-05-25 13:20:39 +01001206
Makoto Onuki83ec63f2019-01-31 17:08:59 -08001207 RunCommand("ANR FILES", {"ls", "-lt", ANR_DIR});
1208
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001209 // Slow traces for slow operations.
Felipe Lemee184f662016-10-27 10:04:47 -07001210 struct stat st;
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001211 int i = 0;
1212 while (true) {
1213 const std::string slow_trace_path =
1214 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
1215 if (stat(slow_trace_path.c_str(), &st)) {
1216 // No traces file at this index, done with the files.
1217 break;
Felipe Lemee184f662016-10-27 10:04:47 -07001218 }
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001219 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
1220 i++;
Felipe Lemee184f662016-10-27 10:04:47 -07001221 }
1222}
1223
Wei Wang509bb5d2017-06-09 14:42:12 -07001224static void DumpBlockStatFiles() {
1225 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -07001226
Wei Wang1dc1ef52017-06-12 11:28:37 -07001227 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
1228
1229 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001230 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1231 return;
1232 }
1233
1234 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -07001235 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001236 if ((d->d_name[0] == '.')
1237 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1238 || (d->d_name[1] == '\0'))) {
1239 continue;
1240 }
1241 const std::string new_path =
1242 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1243 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1244 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1245 printf("\n");
1246 }
Wei Wang1dc1ef52017-06-12 11:28:37 -07001247 return;
Wei Wang509bb5d2017-06-09 14:42:12 -07001248}
Jayachandran Ca94c7172017-06-10 15:08:12 -07001249
1250static void DumpPacketStats() {
1251 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
Jayachandran Ca94c7172017-06-10 15:08:12 -07001252}
1253
1254static void DumpIpAddrAndRules() {
1255 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
Ray Chencbf278a2023-11-20 07:49:45 +00001256 RunCommand("NETWORK INTERFACES", {"ip", "-s", "link"});
Jayachandran Ca94c7172017-06-10 15:08:12 -07001257 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1258 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1259 RunCommand("IP RULES", {"ip", "rule", "show"});
1260 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1261}
1262
Alessio Balsini9e332a72024-12-10 15:31:57 +00001263static void DumpKernelMemoryAllocations() {
1264 if (!access("/proc/allocinfo", F_OK)) {
1265 // Print the top 100 biggest memory allocations of at least one byte.
1266 // The output is sorted by size, descending.
1267 RunCommand("KERNEL MEMORY ALLOCATIONS",
1268 {"alloctop", "--once", "--sort", "s", "--min", "1", "--lines", "100"});
1269 }
1270}
1271
Steven Moreland0d564d52025-01-10 22:24:57 +00001272// BAD - See README.md: "Dumpstate philosophy: exec not link"
1273// This should all be moved into a separate binary rather than have complex logic here.
Nandana Dutt5c390032019-03-12 10:52:56 +00001274static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, int priority,
1275 std::chrono::milliseconds timeout,
1276 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001277 auto start = std::chrono::steady_clock::now();
Vishnu Naire97d6122018-01-18 13:58:56 -08001278 sp<android::IServiceManager> sm = defaultServiceManager();
1279 Dumpsys dumpsys(sm.get());
Vishnu Naire97d6122018-01-18 13:58:56 -08001280 Vector<String16> args;
1281 Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
Vishnu Naire97d6122018-01-18 13:58:56 -08001282 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1283 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001284 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001285 std::string path(title);
1286 path.append(" - ").append(String8(service).c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -08001287 size_t bytes_written = 0;
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001288 if (PropertiesHelper::IsDryRun()) {
1289 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1290 dumpsys.writeDumpFooter(STDOUT_FILENO, service, std::chrono::milliseconds(1));
1291 } else {
Devin Mooref492c1a2023-03-15 19:19:03 +00001292 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP | Dumpsys::TYPE_PID |
1293 Dumpsys::TYPE_CLIENTS | Dumpsys::TYPE_THREAD,
Devin Mooreae68df22023-02-24 20:59:51 +00001294 service, args);
1295 if (status == OK) {
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001296 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1297 std::chrono::duration<double> elapsed_seconds;
1298 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH &&
1299 service == String16("meminfo")) {
1300 // Use a longer timeout for meminfo, since 30s is not always enough.
1301 status = dumpsys.writeDump(STDOUT_FILENO, service, 60s,
1302 /* as_proto = */ false, elapsed_seconds,
1303 bytes_written);
1304 } else {
1305 status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
1306 /* as_proto = */ false, elapsed_seconds,
1307 bytes_written);
1308 }
1309 dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
1310 bool dump_complete = (status == OK);
1311 dumpsys.stopDumpThread(dump_complete);
Devin Moorecdfa4602023-03-16 20:49:39 +00001312 } else {
1313 MYLOGE("Failed to start dump thread for service: %s, status: %d",
1314 String8(service).c_str(), status);
Gavin Corkeryfac7e2b2021-07-08 22:39:02 +01001315 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001316 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001317
1318 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1319 std::chrono::steady_clock::now() - start);
1320 if (elapsed_duration > timeout) {
1321 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1322 elapsed_duration.count());
1323 break;
1324 }
1325 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001326 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001327}
1328
Vishnu Nair64afc022018-02-01 15:29:34 -08001329static void RunDumpsysText(const std::string& title, int priority,
1330 std::chrono::milliseconds timeout,
1331 std::chrono::milliseconds service_timeout) {
1332 DurationReporter duration_reporter(title);
1333 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1334 fsync(STDOUT_FILENO);
1335 RunDumpsysTextByPriority(title, priority, timeout, service_timeout);
1336}
1337
1338/* Dump all services registered with Normal or Default priority. */
Nandana Dutt5c390032019-03-12 10:52:56 +00001339static Dumpstate::RunStatus RunDumpsysTextNormalPriority(const std::string& title,
1340 std::chrono::milliseconds timeout,
1341 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001342 DurationReporter duration_reporter(title);
1343 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1344 fsync(STDOUT_FILENO);
1345 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout,
1346 service_timeout);
Nandana Dutt5c390032019-03-12 10:52:56 +00001347
1348 RETURN_IF_USER_DENIED_CONSENT();
1349
1350 return RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1351 service_timeout);
Vishnu Nair64afc022018-02-01 15:29:34 -08001352}
1353
Steven Moreland0d564d52025-01-10 22:24:57 +00001354// BAD - See README.md: "Dumpstate philosophy: exec not link"
1355// This should all be moved into a separate binary rather than have complex logic here.
Nandana Dutt5c390032019-03-12 10:52:56 +00001356static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priority,
1357 std::chrono::milliseconds timeout,
1358 std::chrono::milliseconds service_timeout) {
Vishnu Naire97d6122018-01-18 13:58:56 -08001359 sp<android::IServiceManager> sm = defaultServiceManager();
1360 Dumpsys dumpsys(sm.get());
1361 Vector<String16> args;
1362 Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
1363 DurationReporter duration_reporter(title);
1364
1365 auto start = std::chrono::steady_clock::now();
1366 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
1367 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001368 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001369 std::string path(kProtoPath);
1370 path.append(String8(service).c_str());
1371 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
1372 path.append("_CRITICAL");
1373 } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
1374 path.append("_HIGH");
1375 }
1376 path.append(kProtoExt);
Steven Morelandcbd69fc2021-07-20 20:45:43 +00001377 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP, service, args);
Vishnu Naire97d6122018-01-18 13:58:56 -08001378 if (status == OK) {
1379 status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
1380 bool dumpTerminated = (status == OK);
1381 dumpsys.stopDumpThread(dumpTerminated);
1382 }
1383 ZipWriter::FileEntry file_entry;
1384 ds.zip_writer_->GetLastEntry(&file_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -08001385
1386 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1387 std::chrono::steady_clock::now() - start);
1388 if (elapsed_duration > timeout) {
1389 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1390 elapsed_duration.count());
1391 break;
1392 }
1393 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001394 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001395}
1396
Nandana Dutta7db6342018-11-21 14:53:34 +00001397// Runs dumpsys on services that must dump first and will take less than 100ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001398static Dumpstate::RunStatus RunDumpsysCritical() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001399 RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1400 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Nandana Dutt5c390032019-03-12 10:52:56 +00001401
1402 RETURN_IF_USER_DENIED_CONSENT();
1403
1404 return RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1405 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Vishnu Nair780b1282017-10-10 13:57:24 -07001406}
1407
1408// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001409static Dumpstate::RunStatus RunDumpsysHigh() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001410 // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
1411 // high priority. Reduce timeout once they are able to dump in a shorter time or
1412 // moved to a parallel task.
1413 RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1414 /* timeout= */ 90s, /* service_timeout= */ 30s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001415
1416 RETURN_IF_USER_DENIED_CONSENT();
1417
1418 return RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1419 /* timeout= */ 5s, /* service_timeout= */ 1s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001420}
1421
1422// Runs dumpsys on services that must dump but can take up to 10s to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001423static Dumpstate::RunStatus RunDumpsysNormal() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001424 RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001425
1426 RETURN_IF_USER_DENIED_CONSENT();
1427
1428 return RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1429 /* timeout= */ 90s, /* service_timeout= */ 10s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001430}
1431
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001432/*
1433 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1434 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1435 * if it's not running in the parallel task.
1436 */
Steven Moreland0d564d52025-01-10 22:24:57 +00001437// BAD - See README.md: "Dumpstate philosophy: exec not link"
1438// This should all be moved into a separate binary rather than have complex logic here.
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001439static void DumpHals(int out_fd = STDOUT_FILENO) {
Yifan Hong30528a22020-08-07 18:24:06 -07001440 RunCommand("HARDWARE HALS", {"lshal", "--all", "--types=all"},
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001441 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build(),
1442 false, out_fd);
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001443
Steven Moreland44cd9482018-01-04 16:24:13 -08001444 using android::hidl::manager::V1_0::IServiceManager;
1445 using android::hardware::defaultServiceManager;
1446
1447 sp<IServiceManager> sm = defaultServiceManager();
1448 if (sm == nullptr) {
1449 MYLOGE("Could not retrieve hwservicemanager to dump hals.\n");
1450 return;
1451 }
1452
1453 auto ret = sm->list([&](const auto& interfaces) {
1454 for (const std::string& interface : interfaces) {
1455 std::string cleanName = interface;
Steven Morelandc6b1fc22023-07-26 23:53:58 +00001456 std::replace_if(
1457 cleanName.begin(), cleanName.end(),
1458 [](char c) {
1459 return !isalnum(c) && std::string("@-_.").find(c) == std::string::npos;
1460 },
1461 '_');
Nandana Dutt979388e2018-11-30 16:48:55 +00001462 const std::string path = ds.bugreport_internal_dir_ + "/lshal_debug_" + cleanName;
Steven Moreland44cd9482018-01-04 16:24:13 -08001463
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001464 bool empty = false;
Steven Moreland44cd9482018-01-04 16:24:13 -08001465 {
1466 auto fd = android::base::unique_fd(
1467 TEMP_FAILURE_RETRY(open(path.c_str(),
1468 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1469 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1470 if (fd < 0) {
1471 MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str());
1472 continue;
1473 }
1474 RunCommandToFd(fd,
1475 "",
Steven Morelandc81cd3c2018-01-18 14:36:26 -08001476 {"lshal", "debug", "-E", interface},
Steven Moreland44cd9482018-01-04 16:24:13 -08001477 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1478
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001479 empty = 0 == lseek(fd, 0, SEEK_END);
Steven Moreland44cd9482018-01-04 16:24:13 -08001480 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001481 if (!empty) {
1482 ds.EnqueueAddZipEntryAndCleanupIfNeeded("lshal-debug/" + cleanName + ".txt",
1483 path);
1484 } else {
1485 unlink(path.c_str());
1486 }
Steven Moreland44cd9482018-01-04 16:24:13 -08001487 }
1488 });
1489
1490 if (!ret.isOk()) {
1491 MYLOGE("Could not list hals from hwservicemanager.\n");
1492 }
1493}
1494
Steven Moreland0d564d52025-01-10 22:24:57 +00001495// BAD - See README.md: "Dumpstate philosophy: exec not link"
1496// This should all be moved into a separate binary rather than have complex logic here.
1497//
Devin Moore8df81bb2022-06-08 22:47:02 +00001498// Dump all of the files that make up the vendor interface.
1499// See the files listed in dumpFileList() for the latest list of files.
1500static void DumpVintf() {
Devin Moore16271d92022-09-22 18:28:48 +00001501
1502 const std::string sku = android::base::GetProperty("ro.boot.product.hardware.sku", "");
1503 const auto vintfFiles = android::vintf::details::dumpFileList(sku);
Devin Moore8df81bb2022-06-08 22:47:02 +00001504 for (const auto vintfFile : vintfFiles) {
1505 struct stat st;
1506 if (stat(vintfFile.c_str(), &st) == 0) {
1507 if (S_ISDIR(st.st_mode)) {
1508 ds.AddDir(vintfFile, true /* recursive */);
1509 } else {
1510 ds.EnqueueAddZipEntryAndCleanupIfNeeded(ZIP_ROOT_DIR + vintfFile,
1511 vintfFile);
1512 }
1513 }
1514 }
1515}
1516
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001517static void DumpExternalFragmentationInfo() {
1518 struct stat st;
1519 if (stat("/proc/buddyinfo", &st) != 0) {
1520 MYLOGE("Unable to dump external fragmentation info\n");
1521 return;
1522 }
1523
1524 printf("------ EXTERNAL FRAGMENTATION INFO ------\n");
1525 std::ifstream ifs("/proc/buddyinfo");
1526 auto unusable_index_regex = std::regex{"Node\\s+([0-9]+),\\s+zone\\s+(\\S+)\\s+(.*)"};
Steven Moreland0d564d52025-01-10 22:24:57 +00001527 // BAD - See README.md: "Dumpstate philosophy: exec not link"
1528 // This should all be moved into a separate binary rather than have complex logic here.
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001529 for (std::string line; std::getline(ifs, line);) {
1530 std::smatch match_results;
1531 if (std::regex_match(line, match_results, unusable_index_regex)) {
1532 std::stringstream free_pages(std::string{match_results[3]});
1533 std::vector<int> free_pages_per_order(std::istream_iterator<int>{free_pages},
1534 std::istream_iterator<int>());
1535
1536 int total_free_pages = 0;
1537 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1538 total_free_pages += (free_pages_per_order[i] * std::pow(2, i));
1539 }
1540
1541 printf("Node %s, zone %8s", match_results[1].str().c_str(),
1542 match_results[2].str().c_str());
1543
1544 int usable_free_pages = total_free_pages;
1545 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1546 auto unusable_index = (total_free_pages - usable_free_pages) /
1547 static_cast<double>(total_free_pages);
1548 printf(" %5.3f", unusable_index);
1549 usable_free_pages -= (free_pages_per_order[i] * std::pow(2, i));
1550 }
1551
1552 printf("\n");
1553 }
1554 }
1555 printf("\n");
1556}
1557
mhasankd451a472020-05-26 18:02:39 -07001558static void DumpstateLimitedOnly() {
EdenSue8fe4522023-11-20 15:37:23 +08001559 // Trimmed-down version of dumpstate to only include a allowlisted
mhasankd451a472020-05-26 18:02:39 -07001560 // set of logs (system log, event log, and system server / system app
1561 // crashes, and networking logs). See b/136273873 and b/138459828
1562 // for context.
1563 DurationReporter duration_reporter("DUMPSTATE");
1564 unsigned long timeout_ms;
1565 // calculate timeout
1566 timeout_ms = logcat_timeout({"main", "system", "crash"});
1567 RunCommand("SYSTEM LOG",
1568 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1569 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1570 timeout_ms = logcat_timeout({"events"});
1571 RunCommand(
1572 "EVENT LOG",
1573 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1574 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1575
1576 printf("========================================================\n");
1577 printf("== Networking Service\n");
1578 printf("========================================================\n");
1579
1580 RunDumpsys("DUMPSYS NETWORK_SERVICE_LIMITED", {"wifi", "-a"},
1581 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hugo Benichiaa162682020-10-30 23:28:56 +09001582 RunDumpsys("DUMPSYS CONNECTIVITY REQUESTS", {"connectivity", "requests"},
1583 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
mhasankd451a472020-05-26 18:02:39 -07001584
1585 printf("========================================================\n");
Chuwei Hecc54a252024-07-25 15:18:36 +09001586 printf("== Networking Policy\n");
1587 printf("========================================================\n");
1588
1589 RunDumpsys("DUMPSYS NETWORK POLICY", {"netpolicy"}, CommandOptions::WithTimeout(90).Build(),
1590 SEC_TO_MSEC(10));
1591
1592 printf("========================================================\n");
mhasankd451a472020-05-26 18:02:39 -07001593 printf("== Dropbox crashes\n");
1594 printf("========================================================\n");
1595
1596 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1597 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1598
Bryan Yuefb85d92024-02-02 13:37:06 +00001599
1600 printf("========================================================\n");
1601 printf("== ANR Traces\n");
1602 printf("========================================================\n");
1603
Bryan Yucf038cf2024-05-08 09:25:25 +00001604 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX);
Bryan Yuefb85d92024-02-02 13:37:06 +00001605 AddAnrTraceFiles();
1606
mhasankd451a472020-05-26 18:02:39 -07001607 printf("========================================================\n");
1608 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1609 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1610 printf("========================================================\n");
1611 printf("== dumpstate: done (id %d)\n", ds.id_);
1612 printf("========================================================\n");
1613}
1614
Rhed Jaoe017f982020-07-21 17:58:41 +08001615/*
1616 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1617 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1618 * if it's not running in the parallel task.
1619 */
1620static void DumpCheckins(int out_fd = STDOUT_FILENO) {
1621 dprintf(out_fd, "========================================================\n");
1622 dprintf(out_fd, "== Checkins\n");
1623 dprintf(out_fd, "========================================================\n");
1624
1625 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"}, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001626 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"}, out_fd);
1627 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"}, out_fd);
1628 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"}, out_fd);
1629 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"}, out_fd);
1630}
1631
1632/*
1633 * Runs dumpsys on activity service to dump all application activities, services
1634 * and providers in the device.
1635 *
1636 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1637 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1638 * if it's not running in the parallel task.
1639 */
1640static void DumpAppInfos(int out_fd = STDOUT_FILENO) {
1641 dprintf(out_fd, "========================================================\n");
1642 dprintf(out_fd, "== Running Application Activities\n");
1643 dprintf(out_fd, "========================================================\n");
1644
1645 // The following dumpsys internally collects output from running apps, so it can take a long
1646 // time. So let's extend the timeout.
1647
1648 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1649
1650 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1651
1652 dprintf(out_fd, "========================================================\n");
1653 dprintf(out_fd, "== Running Application Services (platform)\n");
1654 dprintf(out_fd, "========================================================\n");
1655
1656 RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
1657 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1658
1659 dprintf(out_fd, "========================================================\n");
1660 dprintf(out_fd, "== Running Application Services (non-platform)\n");
1661 dprintf(out_fd, "========================================================\n");
1662
1663 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1664 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1665
1666 dprintf(out_fd, "========================================================\n");
1667 dprintf(out_fd, "== Running Application Providers (platform)\n");
1668 dprintf(out_fd, "========================================================\n");
1669
1670 RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
Rhed Jaob049f182021-01-11 21:08:43 +08001671 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001672
1673 dprintf(out_fd, "========================================================\n");
1674 dprintf(out_fd, "== Running Application Providers (non-platform)\n");
1675 dprintf(out_fd, "========================================================\n");
1676
1677 RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1678 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1679}
1680
Nandana Dutt5c390032019-03-12 10:52:56 +00001681// Dumps various things. Returns early with status USER_CONSENT_DENIED if user denies consent
1682// via the consent they are shown. Ignores other errors that occur while running various
1683// commands. The consent checking is currently done around long running tasks, which happen to
1684// be distributed fairly evenly throughout the function.
Kean Mariotti306633e2022-09-05 16:30:47 +00001685Dumpstate::RunStatus Dumpstate::dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001686 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001687
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001688 // Enqueue slow functions into the thread pool, if the parallel run is enabled.
Aaron Huang24d215d2022-04-27 18:51:16 +08001689 std::future<std::string> dump_hals, dump_incident_report, dump_board, dump_checkins,
Kean Mariottica20f2d2023-12-15 09:34:25 +00001690 dump_netstats_report;
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001691 if (ds.dump_pool_) {
1692 // Pool was shutdown in DumpstateDefaultAfterCritical method in order to
Kean Mariotti306633e2022-09-05 16:30:47 +00001693 // drop root user. Restarts it.
1694 ds.dump_pool_->start(/* thread_counts = */3);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001695
Chris Morinbc223142022-02-04 14:17:11 -08001696 dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
1697 dump_incident_report = ds.dump_pool_->enqueueTask(
1698 DUMP_INCIDENT_REPORT_TASK, &DumpIncidentReport);
Aaron Huang24d215d2022-04-27 18:51:16 +08001699 dump_netstats_report = ds.dump_pool_->enqueueTask(
1700 DUMP_NETSTATS_PROTO_TASK, &DumpNetstatsProto);
Chris Morinbc223142022-02-04 14:17:11 -08001701 dump_board = ds.dump_pool_->enqueueTaskWithFd(
1702 DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
1703 dump_checkins = ds.dump_pool_->enqueueTaskWithFd(DUMP_CHECKINS_TASK, &DumpCheckins, _1);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001704 }
1705
Nandana Dutt5c390032019-03-12 10:52:56 +00001706 // Dump various things. Note that anything that takes "long" (i.e. several seconds) should
1707 // check intermittently (if it's intrerruptable like a foreach on pids) and/or should be wrapped
1708 // in a consent check (via RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK).
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001709 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001710 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001711 DumpBlockStatFiles();
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001712 DumpFile("MEMORY INFO", "/proc/meminfo");
1713 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001714 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001715
Kevin Jeon947922b2022-09-21 00:29:18 +00001716 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "BUGREPORT_PROCDUMP", {"bugreport_procdump"},
1717 CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001718
Sunny Goyal35949782019-11-19 15:54:36 -08001719 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpVisibleWindowViews);
1720
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001721 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1722 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1723 DumpFile("SLAB INFO", "/proc/slabinfo");
1724 DumpFile("ZONEINFO", "/proc/zoneinfo");
1725 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1726 DumpFile("BUDDYINFO", "/proc/buddyinfo");
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001727 DumpExternalFragmentationInfo();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001728
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001729 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001730
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001731 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001732 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001733
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001734 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001735 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_hals));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001736 } else {
1737 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_HALS_TASK, DumpHals);
1738 }
Steven Moreland81b429e2017-01-31 19:50:46 -08001739
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001740 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001741 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001742 struct stat s;
1743 if (stat("/proc/modules", &s) != 0) {
1744 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1745 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001746 RunCommand("LSMOD", {"lsmod"});
Woody Linc198f252021-05-04 16:37:11 +08001747 RunCommand("MODULES INFO",
1748 {"sh", "-c", "cat /proc/modules | cut -d' ' -f1 | "
1749 " while read MOD ; do echo modinfo:$MOD ; modinfo $MOD ; "
1750 "done"}, CommandOptions::AS_ROOT);
Felipe Lemee4eca582016-06-10 17:48:08 -07001751 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001752
Tom Cherryb87dbfa2020-07-28 11:28:53 -07001753 if (android::base::GetBoolProperty("ro.logd.kernel", false)) {
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001754 DoKernelLogcat();
1755 } else {
1756 do_dmesg();
1757 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001758
Devin Moore8df81bb2022-06-08 22:47:02 +00001759 DumpVintf();
1760
Felipe Lemef0292972016-11-22 13:57:05 -08001761 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001762
Jeff Brown1dc94e32014-09-11 14:15:27 -07001763 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001764 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001765
Jack Yu5a6b2e22020-08-14 18:13:35 +08001766 /* Dump Nfc NCI logs */
1767 ds.AddDir("/data/misc/nfc/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001768
Paul Chang0d2aad72020-02-13 20:04:03 +08001769 if (ds.options_->do_screenshot && !ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001770 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001771 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001772 }
1773
Felipe Lemee184f662016-10-27 10:04:47 -07001774 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001775
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001776 MaybeAddSystemTraceToZip();
1777
Narayan Kamath8f788292017-05-25 13:20:39 +01001778 // NOTE: tombstones are always added as separate entries in the zip archive
1779 // and are not interspersed with the main report.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001780 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
Narayan Kamathbd863722017-06-01 18:50:12 +01001781 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001782 if (!tombstones_dumped) {
1783 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001784 }
1785
Jayachandran Ca94c7172017-06-10 15:08:12 -07001786 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001787
Lorenzo Colitti807f2dd2022-05-27 12:48:37 +09001788 RunDumpsys("EBPF MAP STATS", {"connectivity", "trafficcontroller"});
Chenbo Feng276a3b62018-08-07 11:44:49 -07001789
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001790 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001791
Alessio Balsini9e332a72024-12-10 15:31:57 +00001792 DumpKernelMemoryAllocations();
1793
Woody Lin20767a92022-11-29 15:50:24 +08001794 DumpShutdownCheckpoints();
1795
Jayachandran Ca94c7172017-06-10 15:08:12 -07001796 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001797
1798 dump_route_tables();
1799
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001800 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1801 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1802 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001803
Nandana Dutt5c390032019-03-12 10:52:56 +00001804 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysHigh);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001805
Chiachang Wang668ede42021-05-17 17:14:20 +08001806 // The dump mechanism in connectivity is refactored due to modularization work. Connectivity can
1807 // only register with a default priority(NORMAL priority). Dumpstate has to call connectivity
1808 // dump with priority parameters to dump high priority information.
1809 RunDumpsys("SERVICE HIGH connectivity", {"connectivity", "--dump-priority", "HIGH"},
1810 CommandOptions::WithTimeout(10).Build());
1811
Elliott Hughes23ccc622017-02-28 10:14:22 -08001812 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001813
Joe Onoratod38bc3a2023-06-29 15:48:28 -07001814 DumpFile("SYSTEM BUILD-TIME RELEASE FLAGS", "/system/etc/build_flags.json");
1815 DumpFile("SYSTEM_EXT BUILD-TIME RELEASE FLAGS", "/system_ext/etc/build_flags.json");
1816 DumpFile("PRODUCT BUILD-TIME RELEASE FLAGS", "/product/etc/build_flags.json");
1817 DumpFile("VENDOR BUILD-TIME RELEASE FLAGS", "/vendor/etc/build_flags.json");
1818
MÃ¥rten Kongstad5ad813f2023-09-28 10:09:18 +02001819 RunCommand("ACONFIG FLAGS", {PRINT_FLAGS},
1820 CommandOptions::WithTimeout(10).Always().DropRoot().Build());
Ted Bauerf6d61b82024-09-13 19:57:19 +00001821 RunCommand("ACONFIG FLAGS DUMP", {AFLAGS, "list"},
1822 CommandOptions::WithTimeout(10).Always().AsRootIfAvailable().Build());
1823 RunCommand("WHICH ACONFIG FLAG STORAGE", {AFLAGS, "which-backing"},
1824 CommandOptions::WithTimeout(10).Always().AsRootIfAvailable().Build());
Joe Onoratod38bc3a2023-06-29 15:48:28 -07001825
Jin Qianf334d662017-10-10 14:41:37 -07001826 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001827
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001828 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001829
Colin Crossf45fa6b2012-03-26 12:38:26 -07001830 /* Binder state is expensive to look at as it uses a lot of memory. */
Hridya Valsaraju920ba712020-02-09 16:27:01 -08001831 std::string binder_logs_dir = access("/dev/binderfs/binder_logs", R_OK) ?
1832 "/sys/kernel/debug/binder" : "/dev/binderfs/binder_logs";
1833
1834 DumpFile("BINDER FAILED TRANSACTION LOG", binder_logs_dir + "/failed_transaction_log");
1835 DumpFile("BINDER TRANSACTION LOG", binder_logs_dir + "/transaction_log");
1836 DumpFile("BINDER TRANSACTIONS", binder_logs_dir + "/transactions");
1837 DumpFile("BINDER STATS", binder_logs_dir + "/stats");
1838 DumpFile("BINDER STATE", binder_logs_dir + "/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001839
Yifan Hongd90cc652020-02-08 16:52:02 -08001840 ds.AddDir(SNAPSHOTCTL_LOG_DIR, false);
1841
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001842 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001843 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_board));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001844 } else {
1845 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
1846 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001847
Steven Moreland7440ddb2016-12-15 16:13:39 -08001848 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001849 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1850 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001851 // su does not exist on user builds, so try running without it.
1852 // This way any implementations of vril-dump that do not require
1853 // root can run on user builds.
1854 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001855 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001856 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001857 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001858 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001859 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001860 }
1861
Felipe Lemed8b94e52016-12-08 10:21:44 -08001862 printf("========================================================\n");
1863 printf("== Android Framework Services\n");
1864 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001865
Nandana Dutt5c390032019-03-12 10:52:56 +00001866 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001867
Jack He91ff2fe2021-02-18 18:23:43 -08001868 /* Dump Bluetooth HCI logs after getting bluetooth_manager dumpsys */
1869 ds.AddDir("/data/misc/bluetooth/logs", true);
1870
Rhed Jaoe017f982020-07-21 17:58:41 +08001871 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001872 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_checkins));
Rhed Jaoe017f982020-07-21 17:58:41 +08001873 } else {
1874 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_CHECKINS_TASK, DumpCheckins);
1875 }
Dianne Hackborn02bea972013-06-26 18:59:09 -07001876
Rhed Jaoc5f7ec32020-12-22 22:11:08 +08001877 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpAppInfos);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001878
Adrian Roos8b397ab2017-04-04 16:35:44 -07001879 printf("========================================================\n");
1880 printf("== Dropbox crashes\n");
1881 printf("========================================================\n");
1882
1883 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1884 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1885
Felipe Lemed8b94e52016-12-08 10:21:44 -08001886 printf("========================================================\n");
1887 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1888 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1889 printf("========================================================\n");
1890 printf("== dumpstate: done (id %d)\n", ds.id_);
1891 printf("========================================================\n");
Bookatz38472142018-09-28 10:20:24 -07001892
1893 printf("========================================================\n");
1894 printf("== Obtaining statsd metadata\n");
1895 printf("========================================================\n");
1896 // This differs from the usual dumpsys stats, which is the stats report data.
1897 RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
Mike Ma5c267872019-08-21 11:31:34 -07001898
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +09001899 // Add linker configuration directory
1900 ds.AddDir(LINKERCONFIG_DIR, true);
1901
Li Li830179f2022-01-04 12:53:29 -08001902 /* Dump frozen cgroupfs */
1903 dump_frozen_cgroupfs();
Li Li2eedd412021-06-30 15:11:53 -07001904
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001905 if (ds.dump_pool_) {
Aaron Huang24d215d2022-04-27 18:51:16 +08001906 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_netstats_report));
1907 } else {
1908 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_NETSTATS_PROTO_TASK,
1909 DumpNetstatsProto);
1910 }
1911
1912 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001913 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_incident_report));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001914 } else {
1915 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_INCIDENT_REPORT_TASK,
1916 DumpIncidentReport);
1917 }
Mike Ma5c267872019-08-21 11:31:34 -07001918
Kean Mariotti306633e2022-09-05 16:30:47 +00001919 MaybeAddUiTracesToZip();
1920
Nandana Dutt5c390032019-03-12 10:52:56 +00001921 return Dumpstate::RunStatus::OK;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001922}
1923
Nandana Dutt5c390032019-03-12 10:52:56 +00001924/*
1925 * Dumps state for the default case; drops root after it's no longer necessary.
1926 *
1927 * Returns RunStatus::OK if everything went fine.
1928 * Returns RunStatus::ERROR if there was an error.
1929 * Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport
1930 * with the caller.
1931 */
Jichao Lie89d9c12019-11-21 19:02:51 -08001932Dumpstate::RunStatus Dumpstate::DumpstateDefaultAfterCritical() {
Nandana Duttdb379fa2019-10-09 16:54:41 +01001933 // Capture first logcat early on; useful to take a snapshot before dumpstate logs take over the
1934 // buffer.
1935 DoLogcat();
1936 // Capture timestamp after first logcat to use in next logcat
1937 time_t logcat_ts = time(nullptr);
1938
Nandana Dutt4be45d12018-09-26 15:04:23 +01001939 /* collect stack traces from Dalvik and native processes (needs root) */
Chris Morinbc223142022-02-04 14:17:11 -08001940 std::future<std::string> dump_traces;
Rhed Jao5377d792020-07-16 17:37:39 +08001941 if (dump_pool_) {
1942 RETURN_IF_USER_DENIED_CONSENT();
1943 // One thread is enough since we only need to enqueue DumpTraces here.
1944 dump_pool_->start(/* thread_counts = */1);
1945
1946 // DumpTraces takes long time, post it to the another thread in the
1947 // pool, if pool is available
Chris Morinbc223142022-02-04 14:17:11 -08001948 dump_traces = dump_pool_->enqueueTask(
1949 DUMP_TRACES_TASK, &Dumpstate::DumpTraces, &ds, &dump_traces_path);
Rhed Jao5377d792020-07-16 17:37:39 +08001950 } else {
1951 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_TRACES_TASK, ds.DumpTraces,
1952 &dump_traces_path);
1953 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001954
1955 /* Run some operations that require root. */
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001956 if (!PropertiesHelper::IsDryRun()) {
Chris Morinc2cba7a2022-02-01 17:06:50 -08001957 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX);
1958 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX);
Andy Hungd62f7e62024-01-11 15:47:52 -08001959 ds.anr_trace_data_ = GetDumpFds(ANR_DIR, ANR_TRACE_FILE_PREFIX);
Woody Lin20767a92022-11-29 15:50:24 +08001960 ds.shutdown_checkpoints_ = GetDumpFds(
1961 SHUTDOWN_CHECKPOINTS_DIR, SHUTDOWN_CHECKPOINTS_FILE_PREFIX);
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001962 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001963
1964 ds.AddDir(RECOVERY_DIR, true);
1965 ds.AddDir(RECOVERY_DATA_DIR, true);
1966 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
Kelvin Zhang6eaa0f92022-09-12 09:29:19 -07001967 ds.AddDir(UPDATE_ENGINE_PREF_DIR, true);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001968 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1969 if (!PropertiesHelper::IsUserBuild()) {
1970 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1971 ds.AddDir(PROFILE_DATA_DIR_REF, true);
Calin Juravlef84d3692020-04-28 15:31:12 -07001972 ds.AddZipEntry(ZIP_ROOT_DIR + PACKAGE_DEX_USE_LIST, PACKAGE_DEX_USE_LIST);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001973 }
Jerry Changa1df8a92020-01-02 16:03:39 +08001974 ds.AddDir(PREREBOOT_DATA_DIR, false);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001975 add_mountinfo();
Peter Collingbourne78aa2942023-02-15 14:50:31 -08001976 for (const char* path : {"/proc/cpuinfo", "/proc/meminfo"}) {
1977 ds.AddZipEntry(ZIP_ROOT_DIR + path, path);
1978 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001979 DumpIpTablesAsRoot();
David Andersond9ba4752018-12-11 18:26:59 -08001980 DumpDynamicPartitionInfo();
Yifan Hong3945e1b2019-10-29 12:59:23 -07001981 ds.AddDir(OTA_METADATA_DIR, true);
Jeff Sharkey9df29d52023-02-06 14:26:30 -07001982 if (!PropertiesHelper::IsUserBuild()) {
1983 // Include dropbox entry files inside ZIP, but exclude
1984 // noisy WTF and StrictMode entries
1985 dump_files("", DROPBOX_DIR, skip_wtf_strictmode, _add_file_from_fd);
1986 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001987
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001988 // Capture any IPSec policies in play. No keys are exposed here.
Nandana Dutt4be45d12018-09-26 15:04:23 +01001989 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1990
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001991 // Dump IPsec stats. No keys are exposed here.
1992 DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
1993
Nandana Dutt4be45d12018-09-26 15:04:23 +01001994 // Run ss as root so we can see socket marks.
1995 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1996
1997 // Run iotop as root to show top 100 IO threads
1998 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1999
Erick Reyese68df822019-02-11 14:46:36 -08002000 // Gather shared memory buffer info if the product implements it
Hridya Valsaraju1da80c52021-01-09 22:10:11 -08002001 RunCommand("Dmabuf dump", {"dmabuf_dump"});
2002 RunCommand("Dmabuf per-buffer/per-exporter/per-device stats", {"dmabuf_dump", "-b"});
Erick Reyese68df822019-02-11 14:46:36 -08002003
Minchan Kim22c6a1e2019-09-30 15:58:10 -07002004 DumpFile("PSI cpu", "/proc/pressure/cpu");
2005 DumpFile("PSI memory", "/proc/pressure/memory");
2006 DumpFile("PSI io", "/proc/pressure/io");
2007
Steven Moreland9379c462023-12-21 02:04:27 +00002008 ds.AddZipEntry(ZIP_ROOT_DIR + KERNEL_CONFIG, KERNEL_CONFIG);
2009
MÃ¥rten Kongstad60195a72022-09-20 14:14:20 +02002010 RunCommand("SDK EXTENSIONS", {SDK_EXT_INFO, "--dump"},
2011 CommandOptions::WithTimeout(10).Always().DropRoot().Build());
2012
Nattharat Jariyanuntanaetb250cae2024-05-15 07:48:19 +00002013 // Dump UWB UCI logs here because apexdata requires root access
2014 ds.AddDir(UWB_LOG_DIR, true);
2015
Rhed Jao5377d792020-07-16 17:37:39 +08002016 if (dump_pool_) {
2017 RETURN_IF_USER_DENIED_CONSENT();
Chris Morinbc223142022-02-04 14:17:11 -08002018 WaitForTask(std::move(dump_traces));
Rhed Jao5377d792020-07-16 17:37:39 +08002019
Chris Morinbc223142022-02-04 14:17:11 -08002020 // Current running thread in the pool is the root user also. Delete
2021 // the pool and make a new one later to ensure none of threads in the pool are root.
2022 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao5377d792020-07-16 17:37:39 +08002023 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01002024 if (!DropRootUser()) {
Nandana Dutt5c390032019-03-12 10:52:56 +00002025 return Dumpstate::RunStatus::ERROR;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002026 }
2027
Nandana Dutt5c390032019-03-12 10:52:56 +00002028 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttdb379fa2019-10-09 16:54:41 +01002029 Dumpstate::RunStatus status = dumpstate();
2030 // Capture logcat since the last time we did it.
2031 DoSystemLogcat(logcat_ts);
2032 return status;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002033}
2034
Rhed Jaob5685b32020-08-14 17:19:17 +08002035// Common states for telephony and wifi which are needed to be collected before
2036// dumpstate drop the root user.
2037static void DumpstateRadioAsRoot() {
2038 DumpIpTablesAsRoot();
2039 ds.AddDir(LOGPERSIST_DATA_DIR, false);
2040}
2041
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002042// This method collects common dumpsys for telephony and wifi. Typically, wifi
2043// reports are fine to include all information, but telephony reports on user
2044// builds need to strip some content (see DumpstateTelephonyOnly).
2045static void DumpstateRadioCommon(bool include_sensitive_info = true) {
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002046 // We need to be picky about some stuff for telephony reports on user builds.
2047 if (!include_sensitive_info) {
2048 // Only dump the radio log buffer (other buffers and dumps contain too much unrelated info).
2049 DoRadioLogcat();
2050 } else {
Rhed Jaob5685b32020-08-14 17:19:17 +08002051 // DumpHals takes long time, post it to the another thread in the pool,
2052 // if pool is available.
Chris Morinbc223142022-02-04 14:17:11 -08002053 std::future<std::string> dump_hals;
Rhed Jaob5685b32020-08-14 17:19:17 +08002054 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002055 dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
Rhed Jaob5685b32020-08-14 17:19:17 +08002056 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002057 // Contains various system properties and process startup info.
2058 do_dmesg();
2059 // Logs other than the radio buffer may contain package/component names and potential PII.
2060 DoLogcat();
2061 // Too broad for connectivity problems.
2062 DoKmsg();
Rhed Jaob5685b32020-08-14 17:19:17 +08002063 // DumpHals contains unrelated hardware info (camera, NFC, biometrics, ...).
2064 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002065 WaitForTask(std::move(dump_hals));
Rhed Jaob5685b32020-08-14 17:19:17 +08002066 } else {
2067 RUN_SLOW_FUNCTION_AND_LOG(DUMP_HALS_TASK, DumpHals);
2068 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002069 }
2070
Jayachandran Ca94c7172017-06-10 15:08:12 -07002071 DumpPacketStats();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002072 DumpIpAddrAndRules();
2073 dump_route_tables();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002074 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
2075 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08002076}
2077
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002078// We use "telephony" here for legacy reasons, though this now really means "connectivity" (cellular
2079// + wifi + networking). This method collects dumpsys for connectivity debugging only. General rules
2080// for what can be included on user builds: all reported information MUST directly relate to
2081// connectivity debugging or customer support and MUST NOT contain unrelated personally identifiable
2082// information. This information MUST NOT identify user-installed packages (UIDs are OK, package
2083// names are not), and MUST NOT contain logs of user application traffic.
2084// TODO(b/148168577) rename this and other related fields/methods to "connectivity" instead.
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08002085static void DumpstateTelephonyOnly(const std::string& calling_package) {
mukesh agrawal253dad42018-01-23 21:59:59 -08002086 DurationReporter duration_reporter("DUMPSTATE");
Jichao Lie89d9c12019-11-21 19:02:51 -08002087
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002088 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
mukesh agrawal253dad42018-01-23 21:59:59 -08002089
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002090 const bool include_sensitive_info = !PropertiesHelper::IsUserBuild();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002091
Rhed Jaob5685b32020-08-14 17:19:17 +08002092 DumpstateRadioAsRoot();
2093 if (!DropRootUser()) {
2094 return;
2095 }
2096
2097 // Starts thread pool after the root user is dropped, and two additional threads
2098 // are created for DumpHals in the DumpstateRadioCommon and DumpstateBoard.
Chris Morinbc223142022-02-04 14:17:11 -08002099 std::future<std::string> dump_board;
Rhed Jaob5685b32020-08-14 17:19:17 +08002100 if (ds.dump_pool_) {
2101 ds.dump_pool_->start(/*thread_counts =*/2);
2102
2103 // DumpstateBoard takes long time, post it to the another thread in the pool,
2104 // if pool is available.
Chris Morinbc223142022-02-04 14:17:11 -08002105 dump_board = ds.dump_pool_->enqueueTaskWithFd(
2106 DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
Rhed Jaob5685b32020-08-14 17:19:17 +08002107 }
2108
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002109 DumpstateRadioCommon(include_sensitive_info);
2110
2111 if (include_sensitive_info) {
2112 // Contains too much unrelated PII, and given the unstructured nature of sysprops, we can't
2113 // really cherrypick all of the connectivity-related ones. Apps generally have no business
2114 // reading these anyway, and there should be APIs to supply the info in a more app-friendly
2115 // way.
2116 RunCommand("SYSTEM PROPERTIES", {"getprop"});
2117 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002118
2119 printf("========================================================\n");
2120 printf("== Android Framework Services\n");
2121 printf("========================================================\n");
2122
Vishnu Nair652cc802017-11-30 15:18:30 -08002123 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2124 SEC_TO_MSEC(10));
Hunter Knepshield31cbae12021-05-11 16:23:24 -07002125 RunDumpsys("DUMPSYS", {"vcn_management"}, CommandOptions::WithTimeout(90).Build(),
2126 SEC_TO_MSEC(10));
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08002127 if (include_sensitive_info) {
2128 // Carrier apps' services will be dumped below in dumpsys activity service all-non-platform.
2129 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
2130 SEC_TO_MSEC(10));
2131 } else {
2132 // If the caller is a carrier app and has a carrier service, dump it here since we aren't
2133 // running dumpsys activity service all-non-platform below. Due to the increased output, we
2134 // give a higher timeout as well.
2135 RunDumpsys("DUMPSYS", {"carrier_config", "--requesting-package", calling_package},
2136 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(30));
2137 }
2138 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002139 RunDumpsys("DUMPSYS", {"netpolicy"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2140 RunDumpsys("DUMPSYS", {"network_management"}, CommandOptions::WithTimeout(90).Build(),
Sooraj Sasindrane8d98912018-04-20 11:31:55 -07002141 SEC_TO_MSEC(10));
Hunter Knepshield0fe51b12020-03-05 16:58:20 -08002142 RunDumpsys("DUMPSYS", {"telephony.registry"}, CommandOptions::WithTimeout(90).Build(),
2143 SEC_TO_MSEC(10));
Jack Yu773cc032023-03-16 22:43:39 -07002144 RunDumpsys("DUMPSYS", {"isub"}, CommandOptions::WithTimeout(90).Build(),
2145 SEC_TO_MSEC(10));
Grant Menke56698972023-02-24 13:11:07 -08002146 RunDumpsys("DUMPSYS", {"telecom"}, CommandOptions::WithTimeout(90).Build(),
2147 SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002148 if (include_sensitive_info) {
2149 // Contains raw IP addresses, omit from reports on user builds.
2150 RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2151 // Contains raw destination IP/MAC addresses, omit from reports on user builds.
2152 RunDumpsys("DUMPSYS", {"connmetrics"}, CommandOptions::WithTimeout(90).Build(),
2153 SEC_TO_MSEC(10));
2154 // Contains package/component names, omit from reports on user builds.
2155 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
2156 SEC_TO_MSEC(10));
2157 // Contains package names, but should be relatively simple to remove them (also contains
2158 // UIDs already), omit from reports on user builds.
2159 RunDumpsys("BATTERYSTATS", {"deviceidle"}, CommandOptions::WithTimeout(90).Build(),
2160 SEC_TO_MSEC(10));
2161 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002162
2163 printf("========================================================\n");
2164 printf("== Running Application Services\n");
2165 printf("========================================================\n");
2166
2167 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
2168
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002169 if (include_sensitive_info) {
2170 printf("========================================================\n");
2171 printf("== Running Application Services (non-platform)\n");
2172 printf("========================================================\n");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002173
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002174 // Contains package/component names and potential PII, omit from reports on user builds.
2175 // To get dumps of the active CarrierService(s) on user builds, we supply an argument to the
2176 // carrier_config dumpsys instead.
2177 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
2178 DUMPSYS_COMPONENTS_OPTIONS);
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002179
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002180 printf("========================================================\n");
2181 printf("== Checkins\n");
2182 printf("========================================================\n");
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002183
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002184 // Contains package/component names, omit from reports on user builds.
2185 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
2186 }
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002187
2188 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07002189 printf("== dumpstate: done (id %d)\n", ds.id_);
2190 printf("========================================================\n");
Rhed Jaob5685b32020-08-14 17:19:17 +08002191
2192 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002193 WaitForTask(std::move(dump_board));
Rhed Jaob5685b32020-08-14 17:19:17 +08002194 } else {
2195 RUN_SLOW_FUNCTION_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
2196 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002197}
2198
mukesh agrawal253dad42018-01-23 21:59:59 -08002199// This method collects dumpsys for wifi debugging only
2200static void DumpstateWifiOnly() {
2201 DurationReporter duration_reporter("DUMPSTATE");
2202
Rhed Jaob5685b32020-08-14 17:19:17 +08002203 DumpstateRadioAsRoot();
2204 if (!DropRootUser()) {
2205 return;
2206 }
2207
2208 // Starts thread pool after the root user is dropped. Only one additional
2209 // thread is needed for DumpHals in the DumpstateRadioCommon.
2210 if (ds.dump_pool_) {
2211 ds.dump_pool_->start(/*thread_counts =*/1);
2212 }
2213
mukesh agrawal253dad42018-01-23 21:59:59 -08002214 DumpstateRadioCommon();
2215
2216 printf("========================================================\n");
2217 printf("== Android Framework Services\n");
2218 printf("========================================================\n");
2219
2220 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2221 SEC_TO_MSEC(10));
2222 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
2223 SEC_TO_MSEC(10));
2224
2225 printf("========================================================\n");
2226 printf("== dumpstate: done (id %d)\n", ds.id_);
2227 printf("========================================================\n");
2228}
2229
Elis Elliott8e401ad2023-08-08 11:18:59 +00002230// Collects a lightweight dumpstate to be used for debugging onboarding related flows.
2231static void DumpstateOnboardingOnly() {
2232 ds.AddDir(LOGPERSIST_DATA_DIR, false);
2233}
2234
Christopher Ferris83e0e842024-05-31 13:13:34 -07002235static std::string GetTimestamp(const timespec& ts) {
2236 tm tm;
2237 localtime_r(&ts.tv_sec, &tm);
2238
2239 // Reserve enough space for the entire time string, includes the space
2240 // for the '\0' to make the calculations below easier by using size for
2241 // the total string size.
2242 std::string str(sizeof("1970-01-01 00:00:00.123456789+0830"), '\0');
2243 size_t n = strftime(str.data(), str.size(), "%F %H:%M", &tm);
2244 if (n == 0) {
2245 return "TIMESTAMP FAILURE";
2246 }
2247 int num_chars = snprintf(&str[n], str.size() - n, ":%02d.%09ld", tm.tm_sec, ts.tv_nsec);
2248 if (num_chars > str.size() - n) {
2249 return "TIMESTAMP FAILURE";
2250 }
2251 n += static_cast<size_t>(num_chars);
2252 if (strftime(&str[n], str.size() - n, "%z", &tm) == 0) {
2253 return "TIMESTAMP FAILURE";
2254 }
2255 return str;
2256}
2257
2258static std::string GetCmdline(pid_t pid) {
2259 std::string cmdline;
2260 if (!android::base::ReadFileToString(android::base::StringPrintf("/proc/%d/cmdline", pid),
2261 &cmdline)) {
2262 return "UNKNOWN";
2263 }
2264 // There are '\0' terminators between arguments, convert them to spaces.
2265 // But start by skipping all trailing '\0' values.
2266 size_t cur = cmdline.size() - 1;
2267 while (cur != 0 && cmdline[cur] == '\0') {
2268 cur--;
2269 }
2270 if (cur == 0) {
2271 return "UNKNOWN";
2272 }
2273 while ((cur = cmdline.rfind('\0', cur)) != std::string::npos) {
2274 cmdline[cur] = ' ';
2275 }
2276 return cmdline;
2277}
2278
2279static void DumpPidHeader(int fd, pid_t pid, const timespec& ts) {
2280 // For consistency, the header to this message matches the one
2281 // dumped by debuggerd.
2282 dprintf(fd, "\n----- pid %d at %s -----\n", pid, GetTimestamp(ts).c_str());
2283 dprintf(fd, "Cmd line: %s\n", GetCmdline(pid).c_str());
2284}
2285
2286static void DumpPidFooter(int fd, pid_t pid) {
2287 // For consistency, the footer to this message matches the one
2288 // dumped by debuggerd.
2289 dprintf(fd, "----- end %d -----\n", pid);
2290}
2291
2292static bool DumpBacktrace(int fd, pid_t pid, bool is_java_process) {
2293 int ret = dump_backtrace_to_file_timeout(
2294 pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace, 3, fd);
2295 if (ret == -1 && is_java_process) {
2296 // Tried to unwind as a java process, try a native unwind.
2297 dprintf(fd, "Java unwind failed for pid %d, trying a native unwind.\n", pid);
2298 ret = dump_backtrace_to_file_timeout(pid, kDebuggerdNativeBacktrace, 3, fd);
2299 }
2300 return ret != -1;
2301}
2302
Nandana Duttcf419a72019-03-14 10:40:17 +00002303Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
Gavin Corkery789d7a52021-02-24 23:52:35 +00002304 const std::string temp_file_pattern = ds.bugreport_internal_dir_ + "/dumptrace_XXXXXX";
Nandana Duttfaafd522019-03-11 09:23:09 +00002305 const size_t buf_size = temp_file_pattern.length() + 1;
2306 std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
2307 memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
2308
2309 // Create a new, empty file to receive all trace dumps.
2310 //
2311 // TODO: This can be simplified once we remove support for the old style
2312 // dumps. We can have a file descriptor passed in to dump_traces instead
2313 // of creating a file, closing it and then reopening it again.
2314 android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
2315 if (fd < 0) {
2316 MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002317 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002318 }
2319
2320 // Nobody should have access to this temporary file except dumpstate, but we
2321 // temporarily grant 'read' to 'others' here because this file is created
2322 // when tombstoned is still running as root, but dumped after dropping. This
2323 // can go away once support for old style dumping has.
2324 const int chmod_ret = fchmod(fd, 0666);
2325 if (chmod_ret < 0) {
2326 MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002327 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002328 }
2329
2330 std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
2331 if (proc.get() == nullptr) {
2332 MYLOGE("opendir /proc failed: %s\n", strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002333 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002334 }
2335
2336 // Number of times process dumping has timed out. If we encounter too many
2337 // failures, we'll give up.
2338 int timeout_failures = 0;
2339 bool dalvik_found = false;
2340
Jayant Chowdharya0a8eb22022-05-20 03:30:09 +00002341 const std::set<int> hal_pids = get_interesting_pids();
Nandana Duttfaafd522019-03-11 09:23:09 +00002342
2343 struct dirent* d;
2344 while ((d = readdir(proc.get()))) {
Nandana Duttcf419a72019-03-14 10:40:17 +00002345 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttfaafd522019-03-11 09:23:09 +00002346 int pid = atoi(d->d_name);
2347 if (pid <= 0) {
2348 continue;
2349 }
2350
2351 const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
2352 std::string exe;
2353 if (!android::base::Readlink(link_name, &exe)) {
2354 continue;
2355 }
2356
2357 bool is_java_process;
2358 if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
2359 // Don't bother dumping backtraces for the zygote.
2360 if (IsZygote(pid)) {
2361 continue;
2362 }
2363
2364 dalvik_found = true;
2365 is_java_process = true;
2366 } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
2367 is_java_process = false;
2368 } else {
2369 // Probably a native process we don't care about, continue.
2370 continue;
2371 }
2372
2373 // If 3 backtrace dumps fail in a row, consider debuggerd dead.
2374 if (timeout_failures == 3) {
2375 dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
2376 break;
2377 }
2378
Christopher Ferris83e0e842024-05-31 13:13:34 -07002379 timespec start_timespec;
2380 clock_gettime(CLOCK_REALTIME, &start_timespec);
2381 if (IsCached(pid)) {
2382 DumpPidHeader(fd, pid, start_timespec);
2383 dprintf(fd, "Process is cached, skipping backtrace due to high chance of timeout.\n");
2384 DumpPidFooter(fd, pid);
2385 continue;
2386 }
Nandana Duttfaafd522019-03-11 09:23:09 +00002387
Christopher Ferris83e0e842024-05-31 13:13:34 -07002388 const uint64_t start = Nanotime();
2389 if (!DumpBacktrace(fd, pid, is_java_process)) {
2390 if (IsCached(pid)) {
2391 DumpPidHeader(fd, pid, start_timespec);
2392 dprintf(fd, "Backtrace failed, but process has become cached.\n");
2393 DumpPidFooter(fd, pid);
2394 continue;
2395 }
2396
2397 DumpPidHeader(fd, pid, start_timespec);
2398 dprintf(fd, "Backtrace gathering failed, likely due to a timeout.\n");
2399 DumpPidFooter(fd, pid);
2400
2401 dprintf(fd, "\n[dump %s stack %d: %.3fs elapsed]\n",
2402 is_java_process ? "dalvik" : "native", pid,
2403 (float)(Nanotime() - start) / NANOS_PER_SEC);
Nandana Duttfaafd522019-03-11 09:23:09 +00002404 timeout_failures++;
2405 continue;
2406 }
2407
2408 // We've successfully dumped stack traces, reset the failure count
2409 // and write a summary of the elapsed time to the file and continue with the
2410 // next process.
2411 timeout_failures = 0;
2412
2413 dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
2414 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
2415 }
2416
2417 if (!dalvik_found) {
2418 MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
2419 }
2420
Nandana Duttcf419a72019-03-14 10:40:17 +00002421 *path = file_name_buf.release();
2422 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002423}
2424
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002425static dumpstate_hal_hidl::DumpstateMode GetDumpstateHalModeHidl(
2426 const Dumpstate::BugreportMode bugreport_mode) {
2427 switch (bugreport_mode) {
2428 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2429 return dumpstate_hal_hidl::DumpstateMode::FULL;
2430 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2431 return dumpstate_hal_hidl::DumpstateMode::INTERACTIVE;
2432 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2433 return dumpstate_hal_hidl::DumpstateMode::REMOTE;
2434 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2435 return dumpstate_hal_hidl::DumpstateMode::WEAR;
2436 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2437 return dumpstate_hal_hidl::DumpstateMode::CONNECTIVITY;
2438 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2439 return dumpstate_hal_hidl::DumpstateMode::WIFI;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002440 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002441 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2442 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2443 }
2444 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2445}
2446
2447static dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode GetDumpstateHalModeAidl(
2448 const Dumpstate::BugreportMode bugreport_mode) {
2449 switch (bugreport_mode) {
2450 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2451 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::FULL;
2452 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2453 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::INTERACTIVE;
2454 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2455 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::REMOTE;
2456 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2457 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WEAR;
2458 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2459 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::CONNECTIVITY;
2460 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2461 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WIFI;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002462 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002463 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2464 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2465 }
2466 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2467}
2468
Steven Moreland0d564d52025-01-10 22:24:57 +00002469// BAD - See README.md: "Dumpstate philosophy: exec not link"
2470// This should all be moved into a separate binary rather than have complex logic here.
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002471static void DoDumpstateBoardHidl(
2472 const sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_1_0,
2473 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2474 const Dumpstate::BugreportMode bugreport_mode,
2475 const size_t timeout_sec) {
2476
2477 using ScopedNativeHandle =
2478 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
2479 ScopedNativeHandle handle(native_handle_create(static_cast<int>(dumpstate_fds.size()), 0),
2480 [](native_handle_t* handle) {
2481 // we don't close file handle's here
2482 // via native_handle_close(handle)
2483 // instead we let dumpstate_fds close the file handles when
2484 // dumpstate_fds gets destroyed
2485 native_handle_delete(handle);
2486 });
2487 if (handle == nullptr) {
2488 MYLOGE("Could not create native_handle for dumpstate HAL\n");
2489 return;
2490 }
2491
2492 for (size_t i = 0; i < dumpstate_fds.size(); i++) {
2493 handle.get()->data[i] = dumpstate_fds[i].get();
2494 }
2495
2496 // Prefer version 1.1 if available. New devices launching with R are no longer allowed to
2497 // implement just 1.0.
2498 const char* descriptor_to_kill;
2499 using DumpstateBoardTask = std::packaged_task<bool()>;
2500 DumpstateBoardTask dumpstate_board_task;
2501 sp<dumpstate_hal_hidl::IDumpstateDevice> dumpstate_hal(
2502 dumpstate_hal_hidl::IDumpstateDevice::castFrom(dumpstate_hal_1_0));
2503 if (dumpstate_hal != nullptr) {
2504 MYLOGI("Using IDumpstateDevice v1.1 HIDL HAL");
2505
2506 dumpstate_hal_hidl::DumpstateMode dumpstate_hal_mode =
2507 GetDumpstateHalModeHidl(bugreport_mode);
2508
2509 descriptor_to_kill = dumpstate_hal_hidl::IDumpstateDevice::descriptor;
2510 dumpstate_board_task =
2511 DumpstateBoardTask([timeout_sec, dumpstate_hal_mode, dumpstate_hal, &handle]() -> bool {
2512 ::android::hardware::Return<dumpstate_hal_hidl::DumpstateStatus> status =
2513 dumpstate_hal->dumpstateBoard_1_1(handle.get(), dumpstate_hal_mode,
2514 SEC_TO_MSEC(timeout_sec));
2515 if (!status.isOk()) {
2516 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2517 return false;
2518 } else if (status != dumpstate_hal_hidl::DumpstateStatus::OK) {
2519 MYLOGE("dumpstateBoard failed with DumpstateStatus::%s\n",
2520 dumpstate_hal_hidl::toString(status).c_str());
2521 return false;
2522 }
2523 return true;
2524 });
2525 } else {
2526 MYLOGI("Using IDumpstateDevice v1.0 HIDL HAL");
2527
2528 descriptor_to_kill = dumpstate_hal_hidl_1_0::IDumpstateDevice::descriptor;
2529 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal_1_0, &handle]() -> bool {
2530 ::android::hardware::Return<void> status =
2531 dumpstate_hal_1_0->dumpstateBoard(handle.get());
2532 if (!status.isOk()) {
2533 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2534 return false;
2535 }
2536 return true;
2537 });
2538 }
2539 auto result = dumpstate_board_task.get_future();
2540 std::thread(std::move(dumpstate_board_task)).detach();
2541
2542 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2543 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2544 if (!android::base::SetProperty(
2545 "ctl.interface_restart",
2546 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2547 MYLOGE("Couldn't restart dumpstate HAL\n");
2548 }
2549 }
2550 // Wait some time for init to kill dumpstate vendor HAL
2551 constexpr size_t killing_timeout_sec = 10;
2552 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2553 MYLOGE(
2554 "killing dumpstateBoard timed out after %zus, continue and "
2555 "there might be racing in content\n",
2556 killing_timeout_sec);
2557 }
2558}
2559
2560static void DoDumpstateBoardAidl(
2561 const std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal,
2562 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2563 const Dumpstate::BugreportMode bugreport_mode, const size_t timeout_sec) {
2564 MYLOGI("Using IDumpstateDevice AIDL HAL");
2565
2566 const char* descriptor_to_kill;
2567 using DumpstateBoardTask = std::packaged_task<bool()>;
2568 DumpstateBoardTask dumpstate_board_task;
2569 dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode dumpstate_hal_mode =
2570 GetDumpstateHalModeAidl(bugreport_mode);
2571
2572 descriptor_to_kill = dumpstate_hal_aidl::IDumpstateDevice::descriptor;
2573 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal, &dumpstate_fds, dumpstate_hal_mode,
2574 timeout_sec]() -> bool {
2575 auto status = dumpstate_hal->dumpstateBoard(dumpstate_fds, dumpstate_hal_mode, timeout_sec);
2576
2577 if (!status.isOk()) {
2578 MYLOGE("dumpstateBoard failed: %s\n", status.getDescription().c_str());
2579 return false;
2580 }
2581 return true;
2582 });
2583 auto result = dumpstate_board_task.get_future();
2584 std::thread(std::move(dumpstate_board_task)).detach();
2585
2586 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2587 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2588 if (!android::base::SetProperty(
2589 "ctl.interface_restart",
2590 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2591 MYLOGE("Couldn't restart dumpstate HAL\n");
2592 }
2593 }
2594 // Wait some time for init to kill dumpstate vendor HAL
2595 constexpr size_t killing_timeout_sec = 10;
2596 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2597 MYLOGE(
2598 "killing dumpstateBoard timed out after %zus, continue and "
2599 "there might be racing in content\n",
2600 killing_timeout_sec);
2601 }
2602}
2603
2604static std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> GetDumpstateBoardAidlService() {
2605 const std::string aidl_instance_name =
2606 std::string(dumpstate_hal_aidl::IDumpstateDevice::descriptor) + "/default";
2607
2608 if (!AServiceManager_isDeclared(aidl_instance_name.c_str())) {
2609 return nullptr;
2610 }
2611
2612 ndk::SpAIBinder dumpstateBinder(AServiceManager_waitForService(aidl_instance_name.c_str()));
2613
2614 return dumpstate_hal_aidl::IDumpstateDevice::fromBinder(dumpstateBinder);
2615}
2616
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002617void Dumpstate::DumpstateBoard(int out_fd) {
2618 dprintf(out_fd, "========================================================\n");
2619 dprintf(out_fd, "== Board\n");
2620 dprintf(out_fd, "========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08002621
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002622 /*
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002623 * mount debugfs for non-user builds with ro.product.debugfs_restrictions.enabled
Hridya Valsaraju51101602021-04-02 14:32:46 -07002624 * set to true and unmount it after invoking dumpstateBoard_* methods.
2625 * This is to enable debug builds to not have debugfs mounted during runtime.
2626 * It will also ensure that debugfs is only accessed by the dumpstate HAL.
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002627 */
Hridya Valsaraju51101602021-04-02 14:32:46 -07002628 auto mount_debugfs =
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002629 android::base::GetBoolProperty("ro.product.debugfs_restrictions.enabled", false);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002630 if (mount_debugfs) {
2631 RunCommand("mount debugfs", {"mount", "-t", "debugfs", "debugfs", "/sys/kernel/debug"},
2632 AS_ROOT_20);
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002633 RunCommand("chmod debugfs", {"chmod", "0755", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002634 }
2635
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002636 std::vector<std::string> paths;
2637 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07002638 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002639 paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
2640 kDumpstateBoardFiles[i].c_str()));
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002641 remover.emplace_back(android::base::make_scope_guard(
2642 std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002643 }
Jie Song9fbfad02017-06-20 16:29:42 -07002644
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002645 // get dumpstate HAL AIDL implementation
2646 std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal_handle_aidl(
2647 GetDumpstateBoardAidlService());
2648 if (dumpstate_hal_handle_aidl == nullptr) {
2649 MYLOGI("No IDumpstateDevice AIDL implementation\n");
2650 }
2651
2652 // get dumpstate HAL HIDL implementation, only if AIDL HAL implementation not found
2653 sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_handle_hidl_1_0 = nullptr;
2654 if (dumpstate_hal_handle_aidl == nullptr) {
2655 dumpstate_hal_handle_hidl_1_0 = dumpstate_hal_hidl_1_0::IDumpstateDevice::getService();
2656 if (dumpstate_hal_handle_hidl_1_0 == nullptr) {
2657 MYLOGI("No IDumpstateDevice HIDL implementation\n");
2658 }
2659 }
2660
2661 // if neither HIDL nor AIDL implementation found, then return
2662 if (dumpstate_hal_handle_hidl_1_0 == nullptr && dumpstate_hal_handle_aidl == nullptr) {
2663 MYLOGE("Could not find IDumpstateDevice implementation\n");
Wei Wang587eac92018-04-05 12:17:20 -07002664 return;
2665 }
2666
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002667 // this is used to hold the file descriptors and when this variable goes out of scope
2668 // the file descriptors are closed
2669 std::vector<::ndk::ScopedFileDescriptor> dumpstate_fds;
Wei Wang587eac92018-04-05 12:17:20 -07002670
Nandana Dutt5c390032019-03-12 10:52:56 +00002671 // TODO(128270426): Check for consent in between?
Wei Wang587eac92018-04-05 12:17:20 -07002672 for (size_t i = 0; i < paths.size(); i++) {
2673 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
2674
2675 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
2676 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
2677 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
2678 if (fd < 0) {
2679 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
2680 return;
2681 }
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002682
2683 dumpstate_fds.emplace_back(fd.release());
2684 // we call fd.release() here to make sure "fd" does not get closed
2685 // after "fd" goes out of scope after this block.
2686 // "fd" will be closed when "dumpstate_fds" goes out of scope
2687 // i.e. when we exit this function
Wei Wang587eac92018-04-05 12:17:20 -07002688 }
2689
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002690 // Given that bugreport is required to diagnose failures, it's better to set an arbitrary amount
2691 // of timeout for IDumpstateDevice than to block the rest of bugreport. In the timeout case, we
2692 // will kill the HAL and grab whatever it dumped in time.
Michael Eastwood8523ea02022-03-10 16:33:08 -08002693 constexpr size_t timeout_sec = 45;
Wei Wang587eac92018-04-05 12:17:20 -07002694
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002695 if (dumpstate_hal_handle_aidl != nullptr) {
2696 DoDumpstateBoardAidl(dumpstate_hal_handle_aidl, dumpstate_fds, options_->bugreport_mode,
2697 timeout_sec);
2698 } else if (dumpstate_hal_handle_hidl_1_0 != nullptr) {
2699 // run HIDL HAL only if AIDL HAL not found
2700 DoDumpstateBoardHidl(dumpstate_hal_handle_hidl_1_0, dumpstate_fds, options_->bugreport_mode,
2701 timeout_sec);
Wei Wang587eac92018-04-05 12:17:20 -07002702 }
2703
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002704 if (mount_debugfs) {
Hridya Valsaraju51101602021-04-02 14:32:46 -07002705 auto keep_debugfs_mounted =
2706 android::base::GetProperty("persist.dbg.keep_debugfs_mounted", "");
2707 if (keep_debugfs_mounted.empty())
2708 RunCommand("unmount debugfs", {"umount", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002709 }
2710
Wei Wang587eac92018-04-05 12:17:20 -07002711 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
2712 for (size_t i = 0; i < paths.size(); i++) {
2713 struct stat s;
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002714 if (fstat(dumpstate_fds[i].get(), &s) == -1) {
2715 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(), strerror(errno));
Wei Wang587eac92018-04-05 12:17:20 -07002716 file_sizes[i] = -1;
2717 continue;
2718 }
2719 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002720 }
2721
2722 for (size_t i = 0; i < paths.size(); i++) {
2723 if (file_sizes[i] == -1) {
2724 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002725 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002726 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07002727 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002728 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002729 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002730 remover[i].Disable();
2731 EnqueueAddZipEntryAndCleanupIfNeeded(kDumpstateBoardFiles[i], paths[i]);
2732 dprintf(out_fd, "*** See %s entry ***\n", kDumpstateBoardFiles[i].c_str());
Jie Song9fbfad02017-06-20 16:29:42 -07002733 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08002734}
2735
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002736static void ShowUsage() {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002737 fprintf(stderr,
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002738 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o directory] [-p] "
2739 "[-s] [-S] [-q] [-P] [-R] [-L] [-V version]\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002740 " -h: display this help message\n"
2741 " -b: play sound file instead of vibrate, at beginning of job\n"
2742 " -e: play sound file instead of vibrate, at end of job\n"
mhasank2d75c442020-06-11 15:05:25 -07002743 " -o: write to custom directory (only in limited mode)\n"
Abhijeet Kaurbb55a3b2019-06-13 18:07:25 +01002744 " -p: capture screenshot to filename.png\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002745 " -s: write zipped file to control socket (for init)\n"
2746 " -S: write file location to control socket (for init)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002747 " -q: disable vibrate\n"
Abhijeet Kaure370d682019-10-01 16:49:30 +01002748 " -P: send broadcast when started and do progress updates\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002749 " -R: take bugreport in remote mode (shouldn't be used with -P)\n"
Nandana Dutt235864b2019-01-22 12:10:16 +00002750 " -w: start binder service and make it wait for a call to startBugreport\n"
mhasankd451a472020-05-26 18:02:39 -07002751 " -L: output limited information that is safe for submission in feedback reports\n"
Felipe Lemed071c682016-10-20 16:48:00 -07002752 " -v: prints the dumpstate header and exit\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002753}
2754
Wei Liuf87959e2016-08-26 14:51:42 -07002755static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07002756 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07002757}
2758
Felipe Leme1d486fe2016-10-14 18:06:47 -07002759bool Dumpstate::FinishZipFile() {
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002760 // Runs all enqueued adding zip entry and cleanup tasks before finishing the zip file.
2761 if (zip_entry_tasks_) {
2762 zip_entry_tasks_->run(/* do_cancel = */false);
2763 }
2764
Felipe Leme9a523ae2016-10-20 15:10:33 -07002765 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07002766 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07002767 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002768 // Final timestamp
2769 char date[80];
2770 time_t the_real_now_please_stand_up = time(nullptr);
2771 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002772 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002773 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002774
Felipe Leme9a523ae2016-10-20 15:10:33 -07002775 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002776 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08002777 return false;
2778 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07002779 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002780 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08002781 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08002782 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08002783
Felipe Leme0f3fb202016-06-10 17:10:53 -07002784 // Add log file (which contains stderr output) to zip...
2785 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002786 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07002787 MYLOGE("Failed to add dumpstate log to .zip file\n");
2788 return false;
2789 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002790 // TODO: Should truncate the existing file.
2791 // ... and re-open it for further logging.
Nandana Dutta344cb62019-02-22 15:12:35 +00002792 if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
2793 return false;
2794 }
Felipe Leme0f3fb202016-06-10 17:10:53 -07002795 fprintf(stderr, "\n");
2796
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002797 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07002798 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002799 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002800 return false;
2801 }
2802
Felipe Leme1d486fe2016-10-14 18:06:47 -07002803 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
2804 ds.zip_file.reset(nullptr);
2805
Felipe Lemee9d2c542016-11-15 11:48:26 -08002806 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002807 android::os::UnlinkAndLogOnError(tmp_path_);
Felipe Lemec4eee562016-04-21 15:42:55 -07002808
Felipe Leme1e9edc62015-12-21 16:02:13 -08002809 return true;
2810}
Felipe Leme6e01fa62015-11-11 19:35:14 -08002811
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00002812static void SendBroadcast(const std::string& action,
2813 const std::vector<std::string>& args,
2814 int32_t user_id) {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002815 // clang-format off
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00002816 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user",
2817 std::to_string(user_id), "--receiver-foreground",
2818 "--receiver-include-background", "-a", action};
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002819 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08002820
2821 am.insert(am.end(), args.begin(), args.end());
2822
Felipe Leme8d2410e2017-02-08 09:46:08 -08002823 RunCommand("", am,
2824 CommandOptions::WithTimeout(20)
2825 .Log("Sending broadcast: '%s'\n")
2826 .Always()
2827 .DropRoot()
2828 .RedirectStderr()
2829 .Build());
2830}
2831
Felipe Leme35b8cf12017-02-10 15:47:29 -08002832static void Vibrate(int duration_ms) {
2833 // clang-format off
Lais Andrade51156962021-02-22 19:21:35 +00002834 std::vector<std::string> args = {"cmd", "vibrator_manager", "synced", "-f", "-d", "dumpstate",
2835 "oneshot", std::to_string(duration_ms)};
2836 RunCommand("", args,
Felipe Leme35b8cf12017-02-10 15:47:29 -08002837 CommandOptions::WithTimeout(10)
2838 .Log("Vibrate: '%s'\n")
2839 .Always()
2840 .Build());
2841 // clang-format on
2842}
2843
Nandana Dutt979388e2018-11-30 16:48:55 +00002844static void MaybeResolveSymlink(std::string* path) {
2845 std::string resolved_path;
2846 if (android::base::Readlink(*path, &resolved_path)) {
2847 *path = resolved_path;
2848 }
2849}
2850
Nandana Dutt4be45d12018-09-26 15:04:23 +01002851/*
2852 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002853 * and adds the version file. Return false if zip_file could not be open to write.
Nandana Dutt4be45d12018-09-26 15:04:23 +01002854 */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002855static bool PrepareToWriteToFile() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002856 MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2857
Nandana Dutt4be45d12018-09-26 15:04:23 +01002858 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2859 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002860 ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002861 char date[80];
2862 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2863 ds.name_ = date;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002864
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002865 if (ds.options_->telephony_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002866 ds.base_name_ += "-telephony";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002867 } else if (ds.options_->wifi_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002868 ds.base_name_ += "-wifi";
2869 }
2870
Paul Chang0d2aad72020-02-13 20:04:03 +08002871 if (ds.options_->do_screenshot) {
Nandana Dutt9d17b942020-03-26 10:02:59 +00002872 ds.screenshot_path_ = ds.GetPath(ds.CalledByApi() ? "-png.tmp" : ".png");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002873 }
2874 ds.tmp_path_ = ds.GetPath(".tmp");
2875 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2876
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01002877 std::string destination = ds.CalledByApi()
Nandana Dutt54dbd672019-01-11 12:58:05 +00002878 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
Nandana Dutt9a76d202019-01-21 15:56:48 +00002879 : ds.bugreport_internal_dir_.c_str();
Nandana Dutt4be45d12018-09-26 15:04:23 +01002880 MYLOGD(
Nandana Dutt235c6672019-11-14 15:22:32 +00002881 "Bugreport dir: [%s] "
2882 "Base name: [%s] "
2883 "Suffix: [%s] "
2884 "Log path: [%s] "
2885 "Temporary path: [%s] "
2886 "Screenshot path: [%s]\n",
Nandana Dutt9a76d202019-01-21 15:56:48 +00002887 destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2888 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002889
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002890 ds.path_ = ds.GetPath(ds.CalledByApi() ? "-zip.tmp" : ".zip");
2891 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2892 create_parent_dirs(ds.path_.c_str());
2893 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2894 if (ds.zip_file == nullptr) {
2895 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2896 return false;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002897 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002898 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2899 ds.AddTextZipEntry("version.txt", ds.version_);
2900 return true;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002901}
2902
2903/*
Abhijeet Kaure370d682019-10-01 16:49:30 +01002904 * Finalizes writing to the file by zipping the tmp file to the final location,
Nandana Dutt4be45d12018-09-26 15:04:23 +01002905 * printing zipped file status, etc.
2906 */
2907static void FinalizeFile() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002908 bool do_text_file = !ds.FinishZipFile();
2909 if (do_text_file) {
2910 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002911 }
mhasank2d75c442020-06-11 15:05:25 -07002912
2913 std::string final_path = ds.path_;
2914 if (ds.options_->OutputToCustomFile()) {
mhasank3a4cfb42020-06-15 18:06:43 -07002915 final_path = ds.GetPath(ds.options_->out_dir, ".zip");
mhasank2d75c442020-06-11 15:05:25 -07002916 android::os::CopyFileToFile(ds.path_, final_path);
2917 }
2918
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002919 if (ds.options_->stream_to_socket) {
2920 android::os::CopyFileToFd(ds.path_, ds.control_socket_fd_);
2921 } else if (ds.options_->progress_updates_to_socket) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002922 if (do_text_file) {
2923 dprintf(ds.control_socket_fd_,
2924 "FAIL:could not create zip file, check %s "
2925 "for more details\n",
2926 ds.log_path_.c_str());
2927 } else {
mhasank2d75c442020-06-11 15:05:25 -07002928 dprintf(ds.control_socket_fd_, "OK:%s\n", final_path.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002929 }
2930 }
2931}
2932
Nandana Dutt4be45d12018-09-26 15:04:23 +01002933
Nandana Dutt58d72e22018-11-16 10:30:48 +00002934static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2935 switch (mode) {
2936 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2937 return "BUGREPORT_FULL";
2938 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2939 return "BUGREPORT_INTERACTIVE";
2940 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2941 return "BUGREPORT_REMOTE";
2942 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2943 return "BUGREPORT_WEAR";
2944 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2945 return "BUGREPORT_TELEPHONY";
2946 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2947 return "BUGREPORT_WIFI";
Elis Elliott8e401ad2023-08-08 11:18:59 +00002948 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
2949 return "BUGREPORT_ONBOARDING";
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002950 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2951 return "BUGREPORT_DEFAULT";
Nandana Dutt58d72e22018-11-16 10:30:48 +00002952 }
2953}
2954
Steven Leeb573eb82022-11-29 22:31:35 +08002955static bool IsConsentlessBugreportAllowed(const Dumpstate::DumpOptions& options) {
2956 // only BUGREPORT_TELEPHONY does not allow using consentless bugreport
2957 return !options.telephony_only;
2958}
2959
Paul Changf59c2b72020-03-10 02:08:55 +08002960static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options,
2961 bool is_screenshot_requested) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002962 // Modify com.android.shell.BugreportProgressService#isDefaultScreenshotRequired as well for
2963 // default system screenshots.
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002964 options->bugreport_mode = mode;
2965 options->bugreport_mode_string = ModeToString(mode);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002966 switch (mode) {
2967 case Dumpstate::BugreportMode::BUGREPORT_FULL:
Paul Changf59c2b72020-03-10 02:08:55 +08002968 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002969 break;
2970 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002971 // Currently, the dumpstate binder is only used by Shell to update progress.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002972 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002973 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002974 break;
2975 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002976 options->do_vibrate = false;
2977 options->is_remote_mode = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002978 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002979 break;
2980 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
Robert Ginda55ecebd2023-04-03 22:53:13 +00002981 options->do_vibrate = false;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002982 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002983 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002984 break;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002985 // TODO(b/148168577) rename TELEPHONY everywhere to CONNECTIVITY.
Nandana Dutt58d72e22018-11-16 10:30:48 +00002986 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002987 options->telephony_only = true;
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002988 options->do_progress_updates = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002989 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002990 break;
2991 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002992 options->wifi_only = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002993 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002994 break;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002995 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
2996 options->onboarding_only = true;
2997 options->do_screenshot = false;
2998 break;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002999 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
3000 break;
Nandana Dutt58d72e22018-11-16 10:30:48 +00003001 }
3002}
3003
Nandana Dutt58d72e22018-11-16 10:30:48 +00003004static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
Nandana Dutt235c6672019-11-14 15:22:32 +00003005 MYLOGI(
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003006 "do_vibrate: %d stream_to_socket: %d progress_updates_to_socket: %d do_screenshot: %d "
Rhed Jao25f50e02020-08-20 00:10:32 +08003007 "is_remote_mode: %d show_header_only: %d telephony_only: %d "
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00003008 "wifi_only: %d do_progress_updates: %d fd: %d bugreport_mode: %s "
mhasankd451a472020-05-26 18:02:39 -07003009 "limited_only: %d args: %s\n",
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003010 options.do_vibrate, options.stream_to_socket, options.progress_updates_to_socket,
Paul Chang0d2aad72020-02-13 20:04:03 +08003011 options.do_screenshot, options.is_remote_mode, options.show_header_only,
Rhed Jao25f50e02020-08-20 00:10:32 +08003012 options.telephony_only, options.wifi_only,
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00003013 options.do_progress_updates, options.bugreport_fd.get(),
3014 options.bugreport_mode_string.c_str(),
3015 options.limited_only, options.args.c_str());
Nandana Dutt58d72e22018-11-16 10:30:48 +00003016}
3017
Nandana Dutt54dbd672019-01-11 12:58:05 +00003018void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
Kean Mariotti306633e2022-09-05 16:30:47 +00003019 int bugreport_flags,
Nandana Dutt54dbd672019-01-11 12:58:05 +00003020 const android::base::unique_fd& bugreport_fd_in,
Paul Changf59c2b72020-03-10 02:08:55 +08003021 const android::base::unique_fd& screenshot_fd_in,
Kholoud Mohameddef4e432024-05-15 12:47:46 +00003022 bool is_screenshot_requested,
3023 bool skip_user_consent) {
Kean Mariotti306633e2022-09-05 16:30:47 +00003024 this->use_predumped_ui_data = bugreport_flags & BugreportFlag::BUGREPORT_USE_PREDUMPED_UI_DATA;
Gavin Corkerya44686c2022-11-23 18:16:51 +00003025 this->is_consent_deferred = bugreport_flags & BugreportFlag::BUGREPORT_FLAG_DEFER_CONSENT;
Kholoud Mohameddef4e432024-05-15 12:47:46 +00003026 this->skip_user_consent = skip_user_consent;
Nandana Dutt54dbd672019-01-11 12:58:05 +00003027 // Duplicate the fds because the passed in fds don't outlive the binder transaction.
Todd Frederick621533f2022-03-26 02:54:17 +00003028 bugreport_fd.reset(fcntl(bugreport_fd_in.get(), F_DUPFD_CLOEXEC, 0));
3029 screenshot_fd.reset(fcntl(screenshot_fd_in.get(), F_DUPFD_CLOEXEC, 0));
Nandana Dutt58d72e22018-11-16 10:30:48 +00003030
Paul Changf59c2b72020-03-10 02:08:55 +08003031 SetOptionsFromMode(bugreport_mode, this, is_screenshot_requested);
Nandana Dutt58d72e22018-11-16 10:30:48 +00003032}
3033
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003034Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
3035 RunStatus status = RunStatus::OK;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003036 int c;
mhasankd451a472020-05-26 18:02:39 -07003037 while ((c = getopt(argc, argv, "dho:svqzpLPBRSV:w")) != -1) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003038 switch (c) {
3039 // clang-format off
mhasank3a4cfb42020-06-15 18:06:43 -07003040 case 'o': out_dir = optarg; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003041 case 's': stream_to_socket = true; break;
3042 case 'S': progress_updates_to_socket = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003043 case 'v': show_header_only = true; break;
3044 case 'q': do_vibrate = false; break;
Paul Chang0d2aad72020-02-13 20:04:03 +08003045 case 'p': do_screenshot = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003046 case 'P': do_progress_updates = true; break;
3047 case 'R': is_remote_mode = true; break;
mhasankd451a472020-05-26 18:02:39 -07003048 case 'L': limited_only = true; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003049 case 'V':
3050 case 'd':
3051 case 'z':
3052 // compatibility no-op
3053 break;
Nandana Dutt235864b2019-01-22 12:10:16 +00003054 case 'w':
3055 // This was already processed
3056 break;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003057 case 'h':
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003058 status = RunStatus::HELP;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003059 break;
3060 default:
3061 fprintf(stderr, "Invalid option: %c\n", c);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003062 status = RunStatus::INVALID_INPUT;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003063 break;
3064 // clang-format on
3065 }
3066 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08003067
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003068 for (int i = 0; i < argc; i++) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003069 args += argv[i];
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003070 if (i < argc - 1) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003071 args += " ";
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003072 }
3073 }
3074
3075 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
3076 optind = 1;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003077
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003078 return status;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003079}
3080
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003081bool Dumpstate::DumpOptions::ValidateOptions() const {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003082 if (bugreport_fd.get() != -1 && stream_to_socket) {
Nandana Dutt979388e2018-11-30 16:48:55 +00003083 return false;
3084 }
3085
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003086 if ((progress_updates_to_socket || do_progress_updates) && stream_to_socket) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003087 return false;
3088 }
3089
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003090 if (is_remote_mode && (do_progress_updates || stream_to_socket)) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003091 return false;
3092 }
3093 return true;
3094}
3095
Nandana Dutt197661d2018-11-16 16:40:21 +00003096void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
3097 options_ = std::move(options);
3098}
3099
Abhijeet Kaura407fb82020-03-27 12:51:12 +00003100void Dumpstate::Initialize() {
3101 /* gets the sequential id */
3102 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
3103 id_ = ++last_id;
3104 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
3105}
3106
Nandana Duttd2f5f082019-01-18 17:13:52 +00003107Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
3108 Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
Gavin Corkerya44686c2022-11-23 18:16:51 +00003109 HandleRunStatus(status);
3110 return status;
3111}
3112
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003113Dumpstate::RunStatus Dumpstate::Retrieve(int32_t calling_uid, const std::string& calling_package,
Kholoud Mohameddef4e432024-05-15 12:47:46 +00003114 const bool keep_bugreport_on_retrieval,
3115 const bool skip_user_consent) {
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003116 Dumpstate::RunStatus status = RetrieveInternal(calling_uid, calling_package,
Kholoud Mohameddef4e432024-05-15 12:47:46 +00003117 keep_bugreport_on_retrieval,
3118 skip_user_consent);
Gavin Corkerya44686c2022-11-23 18:16:51 +00003119 HandleRunStatus(status);
3120 return status;
3121}
3122
3123Dumpstate::RunStatus Dumpstate::RetrieveInternal(int32_t calling_uid,
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003124 const std::string& calling_package,
Kholoud Mohameddef4e432024-05-15 12:47:46 +00003125 const bool keep_bugreport_on_retrieval,
3126 const bool skip_user_consent) {
3127 if (!android::app::admin::flags::onboarding_consentless_bugreports() || !skip_user_consent) {
3128 consent_callback_ = new ConsentCallback();
3129 const String16 incidentcompanion("incidentcompanion");
3130 sp<android::IBinder> ics(
3131 defaultServiceManager()->checkService(incidentcompanion));
3132 android::String16 package(calling_package.c_str());
3133 if (ics != nullptr) {
3134 MYLOGD("Checking user consent via incidentcompanion service\n");
3135
3136 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
3137 calling_uid, package, String16(), String16(),
3138 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
3139 } else {
3140 MYLOGD(
3141 "Unable to check user consent; incidentcompanion service unavailable\n");
3142 return RunStatus::USER_CONSENT_TIMED_OUT;
3143 }
3144 UserConsentResult consent_result = consent_callback_->getResult();
3145 int timeout_ms = 30 * 1000;
3146 while (consent_result == UserConsentResult::UNAVAILABLE &&
3147 consent_callback_->getElapsedTimeMs() < timeout_ms) {
3148 sleep(1);
3149 consent_result = consent_callback_->getResult();
3150 }
3151 if (consent_result == UserConsentResult::DENIED) {
3152 return RunStatus::USER_CONSENT_DENIED;
3153 }
3154 if (consent_result == UserConsentResult::UNAVAILABLE) {
3155 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3156 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3157 consent_callback_.get());
3158 return RunStatus::USER_CONSENT_TIMED_OUT;
3159 }
Gavin Corkerya44686c2022-11-23 18:16:51 +00003160 }
3161
3162 bool copy_succeeded =
3163 android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003164
3165 if (copy_succeeded && (!android::app::admin::flags::onboarding_bugreport_v2_enabled()
3166 || !keep_bugreport_on_retrieval)) {
3167 android::os::UnlinkAndLogOnError(path_);
Gavin Corkerya44686c2022-11-23 18:16:51 +00003168 }
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003169
Gavin Corkerya44686c2022-11-23 18:16:51 +00003170 return copy_succeeded ? Dumpstate::RunStatus::OK
3171 : Dumpstate::RunStatus::ERROR;
3172}
3173
3174void Dumpstate::HandleRunStatus(Dumpstate::RunStatus status) {
3175 if (listener_ != nullptr) {
Nandana Duttbabf6c72019-01-15 14:11:12 +00003176 switch (status) {
3177 case Dumpstate::RunStatus::OK:
Gavin Corkerya44686c2022-11-23 18:16:51 +00003178 listener_->onFinished(path_.c_str());
Nandana Duttbabf6c72019-01-15 14:11:12 +00003179 break;
3180 case Dumpstate::RunStatus::HELP:
3181 break;
3182 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003183 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00003184 break;
3185 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003186 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
3187 break;
3188 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3189 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
3190 break;
3191 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
3192 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00003193 break;
3194 }
3195 }
Nandana Duttbabf6c72019-01-15 14:11:12 +00003196}
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003197void Dumpstate::Cancel() {
3198 CleanupTmpFiles();
3199 android::os::UnlinkAndLogOnError(log_path_);
3200 for (int i = 0; i < NUM_OF_DUMPS; i++) {
3201 android::os::UnlinkAndLogOnError(ds.bugreport_internal_dir_ + "/" +
3202 kDumpstateBoardFiles[i]);
3203 }
3204 tombstone_data_.clear();
3205 anr_data_.clear();
Andy Hungd62f7e62024-01-11 15:47:52 -08003206 anr_trace_data_.clear();
Woody Lin20767a92022-11-29 15:50:24 +08003207 shutdown_checkpoints_.clear();
Rhed Jao0daac912020-08-21 14:48:20 +08003208
3209 // Instead of shutdown the pool, we delete temporary files directly since
3210 // shutdown blocking the call.
3211 if (dump_pool_) {
3212 dump_pool_->deleteTempFiles();
3213 }
3214 if (zip_entry_tasks_) {
3215 zip_entry_tasks_->run(/*do_cancel =*/ true);
3216 }
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003217}
3218
Kean Mariotti306633e2022-09-05 16:30:47 +00003219void Dumpstate::PreDumpUiData() {
Kean Mariottica20f2d2023-12-15 09:34:25 +00003220 auto snapshot_system_trace = MaybeSnapshotSystemTraceAsync();
Kean Mariotti306633e2022-09-05 16:30:47 +00003221 MaybeSnapshotUiTraces();
Kean Mariottica20f2d2023-12-15 09:34:25 +00003222 MaybeWaitForSnapshotSystemTrace(std::move(snapshot_system_trace));
Kean Mariotti306633e2022-09-05 16:30:47 +00003223}
3224
Nandana Dutt979388e2018-11-30 16:48:55 +00003225/*
3226 * Dumps relevant information to a bugreport based on the given options.
3227 *
3228 * The bugreport can be dumped to a file or streamed to a socket.
3229 *
3230 * How dumping to file works:
3231 * stdout is redirected to a temporary file. This will later become the main bugreport entry.
3232 * stderr is redirected a log file.
3233 *
3234 * The temporary bugreport is then populated via printfs, dumping contents of files and
3235 * output of commands to stdout.
3236 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003237 * A bunch of other files and dumps are added to the zip archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00003238 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003239 * The temporary bugreport file and the log file also get added to the archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00003240 *
mhasank2d75c442020-06-11 15:05:25 -07003241 * Bugreports are first generated in a local directory and later copied to the caller's fd
3242 * or directory if supplied.
Nandana Dutt979388e2018-11-30 16:48:55 +00003243 */
Nandana Duttd2f5f082019-01-18 17:13:52 +00003244Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
3245 const std::string& calling_package) {
Rhed Jao5377d792020-07-16 17:37:39 +08003246 DurationReporter duration_reporter("RUN INTERNAL", /* logcat_only = */true);
Nandana Dutt979388e2018-11-30 16:48:55 +00003247 LogDumpOptions(*options_);
Nandana Dutt197661d2018-11-16 16:40:21 +00003248 if (!options_->ValidateOptions()) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00003249 MYLOGE("Invalid options specified\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003250 return RunStatus::INVALID_INPUT;
3251 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003252 /* set as high priority, and protect from OOM killer */
3253 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003254
Felipe Lemed071c682016-10-20 16:48:00 -07003255 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07003256 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003257 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003258 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003259 } else {
3260 /* fallback to kernels <= 2.6.35 */
3261 oom_adj = fopen("/proc/self/oom_adj", "we");
3262 if (oom_adj) {
3263 fputs("-17", oom_adj);
3264 fclose(oom_adj);
3265 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003266 }
3267
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003268 if (version_ == VERSION_DEFAULT) {
3269 version_ = VERSION_CURRENT;
Michal Karpinski4db754f2015-12-11 18:04:32 +00003270 }
3271
Chris Morin5a50d482022-02-01 17:41:18 -08003272 if (version_ != VERSION_CURRENT) {
3273 MYLOGE("invalid version requested ('%s'); supported values are: ('%s', '%s')\n",
3274 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003275 return RunStatus::INVALID_INPUT;
Felipe Lemed071c682016-10-20 16:48:00 -07003276 }
3277
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003278 if (options_->show_header_only) {
3279 PrintHeader();
3280 return RunStatus::OK;
Felipe Lemed071c682016-10-20 16:48:00 -07003281 }
3282
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003283 MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n",
3284 calling_uid, calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003285
Felipe Leme7447d7c2016-11-03 18:12:22 -07003286 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003287 std::string stats_path =
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003288 android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003289 progress_.reset(new Progress(stats_path));
Felipe Leme7447d7c2016-11-03 18:12:22 -07003290
Sahana Raof35ed432019-07-12 10:47:52 +01003291 if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
3292 MYLOGE("Failed to acquire wake lock: %s\n", strerror(errno));
3293 } else {
3294 // Wake lock will be released automatically on process death
3295 MYLOGD("Wake lock acquired.\n");
3296 }
3297
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08003298 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07003299
Felipe Lemef0292972016-11-22 13:57:05 -08003300 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07003301 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
3302 }
3303
Kevin Jeonfa64e642023-07-27 11:36:41 -04003304 if (PropertiesHelper::IsStrictRun()) {
3305 MYLOGI(
3306 "Running on strict-run mode, which has shorter timeouts "
3307 "(to disable, call 'setprop dumpstate.strict_run false')\n");
3308 }
3309
Nandana Dutt235c6672019-11-14 15:22:32 +00003310 MYLOGI("dumpstate info: id=%d, args='%s', bugreport_mode= %s bugreport format version: %s\n",
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00003311 id_, options_->args.c_str(), options_->bugreport_mode_string.c_str(), version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08003312
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003313 do_early_screenshot_ = options_->do_progress_updates;
Felipe Lemee338bf62015-12-07 14:03:50 -08003314
Christopher Ferrised9354f2014-10-01 17:35:01 -07003315 // If we are going to use a socket, do it as early as possible
3316 // to avoid timeouts from bugreport.
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003317 if (options_->stream_to_socket || options_->progress_updates_to_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07003318 MYLOGD("Opening control socket\n");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003319 control_socket_fd_ = open_socket_fn_("dumpstate");
Nandana Dutta344cb62019-02-22 15:12:35 +00003320 if (control_socket_fd_ == -1) {
3321 return ERROR;
3322 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003323 if (options_->progress_updates_to_socket) {
3324 options_->do_progress_updates = 1;
3325 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07003326 }
3327
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003328 if (!PrepareToWriteToFile()) {
3329 return ERROR;
3330 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08003331
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003332 // Interactive, wear & telephony modes are default to true.
3333 // and may enable from cli option or when using control socket
3334 if (options_->do_progress_updates) {
3335 // clang-format off
3336 std::vector<std::string> am_args = {
3337 "--receiver-permission", "android.permission.DUMP",
3338 };
3339 // clang-format on
3340 // Send STARTED broadcast for apps that listen to bugreport generation events
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003341 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED",
3342 am_args, multiuser_get_user_id(calling_uid));
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003343 if (options_->progress_updates_to_socket) {
3344 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08003345 }
3346 }
3347
Nick Kralevichf3599b32016-01-25 15:05:16 -08003348 /* read /proc/cmdline before dropping root */
3349 FILE *cmdline = fopen("/proc/cmdline", "re");
3350 if (cmdline) {
3351 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
3352 fclose(cmdline);
3353 }
3354
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003355 if (options_->do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08003356 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05003357 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003358
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003359 if (zip_file != nullptr) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003360 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
3361 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003362 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08003363 }
3364 }
3365
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003366 int dup_stdout_fd;
3367 int dup_stderr_fd;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003368 // Redirect stderr to log_path_ for debugging.
3369 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
3370 if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
3371 return ERROR;
3372 }
3373 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
3374 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
3375 strerror(errno));
3376 }
Nandana Dutt979388e2018-11-30 16:48:55 +00003377
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003378 // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
3379 // moved into zip file later, if zipping.
3380 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
3381 // TODO: why not write to a file instead of stdout to overcome this problem?
3382 /* TODO: rather than generating a text file now and zipping it later,
3383 it would be more efficient to redirect stdout to the zip entry
3384 directly, but the libziparchive doesn't support that option yet. */
3385 if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
3386 return ERROR;
3387 }
3388 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
3389 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
3390 tmp_path_.c_str(), strerror(errno));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003391 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08003392
3393 // Don't buffer stdout
3394 setvbuf(stdout, nullptr, _IONBF, 0);
3395
Rhed Jao5377d792020-07-16 17:37:39 +08003396 // Enable the parallel run if the client requests to output to a file.
3397 EnableParallelRunIfNeeded();
3398 // Using scope guard to make sure the dump pool can be shut down correctly.
3399 auto scope_guard_to_shutdown_pool = android::base::make_scope_guard([=]() {
3400 ShutdownDumpPool();
3401 });
3402
Felipe Leme608385d2016-02-01 10:35:38 -08003403 // NOTE: there should be no stdout output until now, otherwise it would break the header.
3404 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08003405 // duration is logged into MYLOG instead.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003406 PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003407
Kean Mariottic14cebc2024-03-04 10:55:28 +00003408 bool system_trace_exists = access(SYSTEM_TRACE_SNAPSHOT, F_OK) == 0;
3409 if (options_->use_predumped_ui_data && !system_trace_exists) {
3410 MYLOGW("Ignoring 'use predumped data' flag because no predumped data is available");
3411 options_->use_predumped_ui_data = false;
3412 }
3413
Kean Mariottica20f2d2023-12-15 09:34:25 +00003414 std::future<std::string> snapshot_system_trace;
3415
Kean Mariotti853b73a2023-07-27 12:40:30 +00003416 bool is_dumpstate_restricted =
3417 options_->telephony_only || options_->wifi_only || options_->limited_only;
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003418 if (!is_dumpstate_restricted) {
3419 // Snapshot the system trace now (if running) to avoid that dumpstate's
3420 // own activity pushes out interesting data from the trace ring buffer.
3421 // The trace file is added to the zip by MaybeAddSystemTraceToZip().
Kean Mariottica20f2d2023-12-15 09:34:25 +00003422 snapshot_system_trace = MaybeSnapshotSystemTraceAsync();
Yohei Yukawa95305b32021-03-09 07:54:27 -08003423
Kean Mariotti853b73a2023-07-27 12:40:30 +00003424 // Invoke critical dumpsys to preserve system state, before doing anything else.
3425 RunDumpsysCritical();
3426
Kean Mariotti306633e2022-09-05 16:30:47 +00003427 // Snapshot the UI traces now (if running).
3428 // The trace files will be added to bugreport later.
3429 MaybeSnapshotUiTraces();
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003430 }
Kean Mariotti853b73a2023-07-27 12:40:30 +00003431
3432 MaybeTakeEarlyScreenshot();
Kean Mariottica20f2d2023-12-15 09:34:25 +00003433 MaybeWaitForSnapshotSystemTrace(std::move(snapshot_system_trace));
Gavin Corkery6968f552020-11-22 18:09:05 +00003434 onUiIntensiveBugreportDumpsFinished(calling_uid);
3435 MaybeCheckUserConsent(calling_uid, calling_package);
3436 if (options_->telephony_only) {
3437 DumpstateTelephonyOnly(calling_package);
3438 } else if (options_->wifi_only) {
3439 DumpstateWifiOnly();
3440 } else if (options_->limited_only) {
3441 DumpstateLimitedOnly();
Elis Elliott8e401ad2023-08-08 11:18:59 +00003442 } else if (options_->onboarding_only) {
3443 DumpstateOnboardingOnly();
Gavin Corkery6968f552020-11-22 18:09:05 +00003444 } else {
Nandana Dutt4be45d12018-09-26 15:04:23 +01003445 // Dump state for the default case. This also drops root.
Jichao Lie89d9c12019-11-21 19:02:51 -08003446 RunStatus s = DumpstateDefaultAfterCritical();
Nandana Dutt5c390032019-03-12 10:52:56 +00003447 if (s != RunStatus::OK) {
Nandana Duttaac6f582019-07-26 14:32:47 +01003448 if (s == RunStatus::USER_CONSENT_DENIED) {
Nandana Dutt5c390032019-03-12 10:52:56 +00003449 HandleUserConsentDenied();
3450 }
3451 return s;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08003452 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07003453 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07003454
Felipe Leme55b42a62015-11-10 17:39:08 -08003455 /* close output if needed */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003456 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003457
Abhijeet Kaure370d682019-10-01 16:49:30 +01003458 // Zip the (now complete) .tmp file within the internal directory.
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003459 ATRACE_BEGIN("FinalizeFile");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003460 FinalizeFile();
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003461 ATRACE_END();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003462
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003463 // Share the final file with the caller if the user has consented or Shell is the caller.
Nandana Duttd2f5f082019-01-18 17:13:52 +00003464 Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
Gavin Corkerya44686c2022-11-23 18:16:51 +00003465 if (CalledByApi() && !options_->is_consent_deferred) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003466 status = CopyBugreportIfUserConsented(calling_uid);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003467 if (status != Dumpstate::RunStatus::OK &&
3468 status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3469 // Do an early return if there were errors. We make an exception for consent
3470 // timing out because it's possible the user got distracted. In this case the
3471 // bugreport is not shared but made available for manual retrieval.
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003472 MYLOGI("User denied consent. Returning\n");
Nandana Duttd2f5f082019-01-18 17:13:52 +00003473 return status;
3474 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003475 if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3476 MYLOGI(
3477 "Did not receive user consent yet."
3478 " Will not copy the bugreport artifacts to caller.\n");
Abhijeet Kaur57627412019-04-17 16:00:09 +01003479 const String16 incidentcompanion("incidentcompanion");
3480 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
3481 if (ics != nullptr) {
3482 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3483 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3484 consent_callback_.get());
3485 } else {
3486 MYLOGD("Unable to cancel user consent; incidentcompanion service unavailable\n");
3487 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003488 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003489 }
3490
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003491 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003492 if (options_->do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09003493 for (int i = 0; i < 3; i++) {
3494 Vibrate(75);
3495 usleep((75 + 50) * 1000);
3496 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003497 }
3498
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003499 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
3500 progress_->GetInitialMax());
3501 progress_->Save();
3502 MYLOGI("done (id %d)\n", id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003503
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003504 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08003505
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003506 if (control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07003507 MYLOGD("Closing control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003508 close(control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07003509 }
3510
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003511 tombstone_data_.clear();
3512 anr_data_.clear();
Andy Hungd62f7e62024-01-11 15:47:52 -08003513 anr_trace_data_.clear();
Woody Lin20767a92022-11-29 15:50:24 +08003514 shutdown_checkpoints_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01003515
Nandana Duttd2f5f082019-01-18 17:13:52 +00003516 return (consent_callback_ != nullptr &&
3517 consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
3518 ? USER_CONSENT_TIMED_OUT
3519 : RunStatus::OK;
3520}
3521
Paul Chang0d2aad72020-02-13 20:04:03 +08003522void Dumpstate::MaybeTakeEarlyScreenshot() {
3523 if (!options_->do_screenshot || !do_early_screenshot_) {
3524 return;
3525 }
3526
3527 TakeScreenshot();
3528}
3529
Kean Mariottica20f2d2023-12-15 09:34:25 +00003530std::future<std::string> Dumpstate::MaybeSnapshotSystemTraceAsync() {
Kean Mariotti853b73a2023-07-27 12:40:30 +00003531 // When capturing traces via bugreport handler (BH), this function will be invoked twice:
3532 // 1) When BH invokes IDumpstate::PreDumpUiData()
3533 // 2) When BH invokes IDumpstate::startBugreport(flags = BUGREPORT_USE_PREDUMPED_UI_DATA)
3534 // In this case we don't want to re-invoke perfetto in step 2.
3535 // In all other standard invocation states, this function is invoked once
3536 // without the flag BUGREPORT_USE_PREDUMPED_UI_DATA.
Kean Mariottica20f2d2023-12-15 09:34:25 +00003537 // This function must run asynchronously to avoid delaying MaybeTakeEarlyScreenshot() in the
3538 // standard invocation states (b/316110955).
Kean Mariotti853b73a2023-07-27 12:40:30 +00003539 if (options_->use_predumped_ui_data) {
Kean Mariottica20f2d2023-12-15 09:34:25 +00003540 return {};
3541 }
3542
3543 // Create temporary file for the command's output
3544 std::string outPath = ds.bugreport_internal_dir_ + "/tmp_serialize_perfetto_trace";
3545 auto outFd = android::base::unique_fd(TEMP_FAILURE_RETRY(
3546 open(outPath.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
3547 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
3548 if (outFd < 0) {
3549 MYLOGE("Could not open %s to serialize perfetto trace.\n", outPath.c_str());
3550 return {};
Kean Mariotti853b73a2023-07-27 12:40:30 +00003551 }
3552
3553 // If a stale file exists already, remove it.
3554 unlink(SYSTEM_TRACE_SNAPSHOT);
3555
Kean Mariottica20f2d2023-12-15 09:34:25 +00003556 MYLOGI("Launching async '%s'", SERIALIZE_PERFETTO_TRACE_TASK.c_str())
3557 return std::async(
3558 std::launch::async, [this, outPath = std::move(outPath), outFd = std::move(outFd)] {
3559 // If a background system trace is happening and is marked as "suitable for
3560 // bugreport" (i.e. bugreport_score > 0 in the trace config), this command
3561 // will stop it and serialize into SYSTEM_TRACE_SNAPSHOT. In the (likely)
3562 // case that no trace is ongoing, this command is a no-op.
3563 // Note: this should not be enqueued as we need to freeze the trace before
3564 // dumpstate starts. Otherwise the trace ring buffers will contain mostly
3565 // the dumpstate's own activity which is irrelevant.
3566 RunCommand(
3567 SERIALIZE_PERFETTO_TRACE_TASK, {"perfetto", "--save-for-bugreport"},
3568 CommandOptions::WithTimeout(10).DropRoot().CloseAllFileDescriptorsOnExec().Build(),
3569 false, outFd);
3570 // MaybeAddSystemTraceToZip() will take care of copying the trace in the zip
3571 // file in the later stages.
3572
3573 return outPath;
3574 });
3575}
3576
3577void Dumpstate::MaybeWaitForSnapshotSystemTrace(std::future<std::string> task) {
3578 if (!task.valid()) {
3579 return;
3580 }
3581
3582 WaitForTask(std::move(task), SERIALIZE_PERFETTO_TRACE_TASK, STDOUT_FILENO);
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003583}
3584
Kean Mariotti306633e2022-09-05 16:30:47 +00003585void Dumpstate::MaybeSnapshotUiTraces() {
3586 if (PropertiesHelper::IsUserBuild() || options_->use_predumped_ui_data) {
3587 return;
3588 }
3589
Pablo Gamito654831c2024-02-16 16:47:48 +00003590 std::vector<std::vector<std::string>> dumpTracesForBugReportCommands = {
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003591 {"cmd", "input_method", "tracing", "save-for-bugreport"},
3592 {"cmd", "window", "tracing", "save-for-bugreport"},
3593 {"cmd", "window", "shell", "tracing", "save-for-bugreport"},
3594 };
Hongwei Wang39229132023-01-24 15:09:59 -08003595
Pablo Gamito654831c2024-02-16 16:47:48 +00003596 if (!android_tracing_perfetto_transition_tracing()) {
3597 dumpTracesForBugReportCommands.push_back({"dumpsys", "activity", "service",
3598 "SystemUIService", "WMShell", "transitions",
3599 "tracing", "save-for-bugreport"});
3600 }
3601
Pablo Gamito6929a0e2024-02-26 23:29:47 +00003602 if (!android_tracing_perfetto_protolog_tracing()) {
Pablo Gamito654831c2024-02-16 16:47:48 +00003603 dumpTracesForBugReportCommands.push_back({"dumpsys", "activity", "service",
3604 "SystemUIService", "WMShell", "protolog",
3605 "save-for-bugreport"});
3606 }
3607
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003608 for (const auto& command : dumpTracesForBugReportCommands) {
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003609 RunCommand(
3610 // Empty name because it's not intended to be classified as a bugreport section.
3611 // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003612 "", command,
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003613 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
3614 }
Kean Mariotti306633e2022-09-05 16:30:47 +00003615}
3616
3617void Dumpstate::MaybeAddUiTracesToZip() {
3618 if (PropertiesHelper::IsUserBuild()) {
3619 return;
3620 }
3621
3622 ds.AddDir(WMTRACE_DATA_DIR, false);
Yohei Yukawa95305b32021-03-09 07:54:27 -08003623}
3624
Paul Changeb4b4642020-05-28 22:05:47 +08003625void Dumpstate::onUiIntensiveBugreportDumpsFinished(int32_t calling_uid) {
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003626 if (multiuser_get_app_id(calling_uid) == AID_SHELL || !CalledByApi()) {
Paul Changc490e662020-04-11 18:14:09 +08003627 return;
3628 }
3629 if (listener_ != nullptr) {
3630 // Let listener know ui intensive bugreport dumps are finished, then it can do event
3631 // handling if required.
Paul Changeb4b4642020-05-28 22:05:47 +08003632 listener_->onUiIntensiveBugreportDumpsFinished();
Paul Changc490e662020-04-11 18:14:09 +08003633 }
3634}
3635
Jichao Lie89d9c12019-11-21 19:02:51 -08003636void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) {
Gavin Corkerya44686c2022-11-23 18:16:51 +00003637 if (multiuser_get_app_id(calling_uid) == AID_SHELL ||
Kholoud Mohameddef4e432024-05-15 12:47:46 +00003638 !CalledByApi() || options_->is_consent_deferred ||
3639 (android::app::admin::flags::onboarding_consentless_bugreports() &&
3640 options_->skip_user_consent)) {
Gavin Corkerya44686c2022-11-23 18:16:51 +00003641 // No need to get consent for shell triggered dumpstates, or not
3642 // through bugreporting API (i.e. no fd to copy back), or when consent
3643 // is deferred.
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003644 return;
3645 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003646 consent_callback_ = new ConsentCallback();
3647 const String16 incidentcompanion("incidentcompanion");
3648 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
Jichao Lie89d9c12019-11-21 19:02:51 -08003649 android::String16 package(calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003650 if (ics != nullptr) {
3651 MYLOGD("Checking user consent via incidentcompanion service\n");
Steven Leeb573eb82022-11-29 22:31:35 +08003652 int flags = 0x1; // IncidentManager.FLAG_CONFIRMATION_DIALOG
3653 if (IsConsentlessBugreportAllowed(*options_)) {
3654 flags |= 0x2; // IncidentManager.FLAG_ALLOW_CONSENTLESS_BUGREPORT
3655 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003656 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
Steven Leeb573eb82022-11-29 22:31:35 +08003657 calling_uid, package, String16(), String16(), flags, consent_callback_.get());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003658 } else {
3659 MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
3660 }
3661}
3662
Nandana Dutt5c390032019-03-12 10:52:56 +00003663bool Dumpstate::IsUserConsentDenied() const {
3664 return ds.consent_callback_ != nullptr &&
3665 ds.consent_callback_->getResult() == UserConsentResult::DENIED;
3666}
3667
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01003668bool Dumpstate::CalledByApi() const {
3669 return ds.options_->bugreport_fd.get() != -1 ? true : false;
3670}
3671
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003672void Dumpstate::CleanupTmpFiles() {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003673 android::os::UnlinkAndLogOnError(tmp_path_);
3674 android::os::UnlinkAndLogOnError(screenshot_path_);
3675 android::os::UnlinkAndLogOnError(path_);
Gavin Corkery789d7a52021-02-24 23:52:35 +00003676 if (dump_traces_path != nullptr) {
3677 android::os::UnlinkAndLogOnError(dump_traces_path);
3678 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003679}
3680
Rhed Jao5377d792020-07-16 17:37:39 +08003681void Dumpstate::EnableParallelRunIfNeeded() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003682 if (!PropertiesHelper::IsParallelRun()) {
Rhed Jao5377d792020-07-16 17:37:39 +08003683 return;
3684 }
3685 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003686 zip_entry_tasks_ = std::make_unique<TaskQueue>();
Rhed Jao5377d792020-07-16 17:37:39 +08003687}
3688
3689void Dumpstate::ShutdownDumpPool() {
3690 if (dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08003691 dump_pool_.reset();
Rhed Jao5377d792020-07-16 17:37:39 +08003692 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003693 if (zip_entry_tasks_) {
3694 zip_entry_tasks_->run(/* do_cancel = */true);
3695 zip_entry_tasks_ = nullptr;
3696 }
3697}
3698
3699void Dumpstate::EnqueueAddZipEntryAndCleanupIfNeeded(const std::string& entry_name,
3700 const std::string& entry_path) {
3701 auto func_add_zip_entry_and_cleanup = [=](bool task_cancelled) {
3702 if (!task_cancelled) {
3703 AddZipEntry(entry_name, entry_path);
3704 }
3705 android::os::UnlinkAndLogOnError(entry_path);
3706 };
3707 if (zip_entry_tasks_) {
3708 // Enqueues AddZipEntryAndCleanup function if the parallel run is enabled.
3709 zip_entry_tasks_->add(func_add_zip_entry_and_cleanup, _1);
3710 } else {
3711 // Invokes AddZipEntryAndCleanup immediately
3712 std::invoke(func_add_zip_entry_and_cleanup, /* task_cancelled = */false);
3713 }
Rhed Jao5377d792020-07-16 17:37:39 +08003714}
3715
Nandana Duttd2f5f082019-01-18 17:13:52 +00003716Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
3717 MYLOGD("User denied consent; deleting files and returning\n");
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003718 CleanupTmpFiles();
Nandana Duttd2f5f082019-01-18 17:13:52 +00003719 return USER_CONSENT_DENIED;
3720}
3721
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003722Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented(int32_t calling_uid) {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003723 // If the caller has asked to copy the bugreport over to their directory, we need explicit
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003724 // user consent (unless the caller is Shell).
3725 UserConsentResult consent_result;
Kholoud Mohameddef4e432024-05-15 12:47:46 +00003726 if (multiuser_get_app_id(calling_uid) == AID_SHELL || (options_->skip_user_consent
3727 && android::app::admin::flags::onboarding_consentless_bugreports())) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003728 consent_result = UserConsentResult::APPROVED;
3729 } else {
3730 consent_result = consent_callback_->getResult();
3731 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003732 if (consent_result == UserConsentResult::UNAVAILABLE) {
3733 // User has not responded yet.
3734 uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
Hunter Knepshield70610fa2020-01-03 15:27:33 -08003735 // Telephony is a fast report type, particularly on user builds where information may be
3736 // more aggressively limited. To give the user time to read the consent dialog, increase the
3737 // timeout.
3738 uint64_t timeout_ms = options_->telephony_only ? TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS
3739 : USER_CONSENT_TIMEOUT_MS;
3740 if (elapsed_ms < timeout_ms) {
3741 uint delay_seconds = (timeout_ms - elapsed_ms) / 1000;
Nandana Duttd2f5f082019-01-18 17:13:52 +00003742 MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
3743 sleep(delay_seconds);
3744 }
3745 consent_result = consent_callback_->getResult();
3746 }
3747 if (consent_result == UserConsentResult::DENIED) {
3748 // User has explicitly denied sharing with the app. To be safe delete the
3749 // internal bugreport & tmp files.
3750 return HandleUserConsentDenied();
3751 }
3752 if (consent_result == UserConsentResult::APPROVED) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00003753 bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
3754 if (copy_succeeded) {
3755 android::os::UnlinkAndLogOnError(path_);
Abhijeet Kaur9ce94672020-04-01 17:22:36 +01003756 if (options_->do_screenshot &&
3757 options_->screenshot_fd.get() != -1 &&
3758 !options_->is_screenshot_copied) {
3759 copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
3760 options_->screenshot_fd.get());
3761 options_->is_screenshot_copied = copy_succeeded;
3762 if (copy_succeeded) {
3763 android::os::UnlinkAndLogOnError(screenshot_path_);
3764 }
3765 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003766 }
3767 return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
3768 } else if (consent_result == UserConsentResult::UNAVAILABLE) {
3769 // consent_result is still UNAVAILABLE. The user has likely not responded yet.
3770 // Since we do not have user consent to share the bugreport it does not get
3771 // copied over to the calling app but remains in the internal directory from
3772 // where the user can manually pull it.
Paul Changce644212021-05-11 16:06:45 +08003773 std::string final_path = GetPath(".zip");
3774 bool copy_succeeded = android::os::CopyFileToFile(path_, final_path);
3775 if (copy_succeeded) {
3776 android::os::UnlinkAndLogOnError(path_);
3777 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003778 return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
3779 }
3780 // Unknown result; must be a programming error.
3781 MYLOGE("Unknown user consent result:%d\n", consent_result);
3782 return Dumpstate::RunStatus::ERROR;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003783}
3784
Nandana Duttf02564e2019-02-15 15:24:24 +00003785Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003786 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
3787 Dumpstate::RunStatus status = options->Initialize(argc, argv);
3788 if (status == Dumpstate::RunStatus::OK) {
Nandana Duttf02564e2019-02-15 15:24:24 +00003789 SetOptions(std::move(options));
Nandana Duttd2f5f082019-01-18 17:13:52 +00003790 // When directly running dumpstate binary, the output is not expected to be written
3791 // to any external file descriptor.
Nandana Duttf02564e2019-02-15 15:24:24 +00003792 assert(options_->bugreport_fd.get() == -1);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003793
3794 // calling_uid and calling_package are for user consent to share the bugreport with
Abhijeet Kaura407fb82020-03-27 12:51:12 +00003795 // an app; they are irrelevant here because bugreport is triggered via command line.
3796 // Update Last ID before calling Run().
3797 Initialize();
Nikhil Kumarb70622a2023-06-15 15:37:19 +01003798 status = Run(0 /* calling_uid */, "" /* calling_package */);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003799 }
Nandana Duttf02564e2019-02-15 15:24:24 +00003800 return status;
3801}
3802
3803/* Main entry point for dumpstate binary. */
3804int run_main(int argc, char* argv[]) {
3805 Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003806
3807 switch (status) {
3808 case Dumpstate::RunStatus::OK:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003809 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003810 case Dumpstate::RunStatus::HELP:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003811 ShowUsage();
3812 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003813 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003814 fprintf(stderr, "Invalid combination of args\n");
3815 ShowUsage();
3816 exit(1);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003817 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003818 FALLTHROUGH_INTENDED;
3819 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3820 FALLTHROUGH_INTENDED;
3821 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003822 exit(2);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003823 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003824}
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003825
3826// TODO(111441001): Default DumpOptions to sensible values.
3827Dumpstate::Dumpstate(const std::string& version)
3828 : pid_(getpid()),
3829 options_(new Dumpstate::DumpOptions()),
Nandana Dutt402a8392019-06-14 14:25:13 +01003830 last_reported_percent_progress_(0),
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003831 version_(version),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003832 now_(time(nullptr)),
3833 open_socket_fn_(open_socket) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003834}
3835
3836Dumpstate& Dumpstate::GetInstance() {
3837 static Dumpstate singleton_(android::base::GetProperty("dumpstate.version", VERSION_CURRENT));
3838 return singleton_;
3839}
3840
Rhed Jao5377d792020-07-16 17:37:39 +08003841DurationReporter::DurationReporter(const std::string& title, bool logcat_only, bool verbose,
3842 int duration_fd) : title_(title), logcat_only_(logcat_only), verbose_(verbose),
3843 duration_fd_(duration_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003844 if (!title_.empty()) {
3845 started_ = Nanotime();
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003846 if (title_.find("SHOW MAP") == std::string::npos) {
3847 ATRACE_ASYNC_BEGIN(title_.c_str(), 0);
3848 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003849 }
3850}
3851
3852DurationReporter::~DurationReporter() {
3853 if (!title_.empty()) {
3854 float elapsed = (float)(Nanotime() - started_) / NANOS_PER_SEC;
chenqiwuaf8b2d92019-12-12 18:53:51 +08003855 if (elapsed >= .5f || verbose_) {
3856 MYLOGD("Duration of '%s': %.2fs\n", title_.c_str(), elapsed);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003857 }
chenqiwuaf8b2d92019-12-12 18:53:51 +08003858 if (!logcat_only_) {
3859 // Use "Yoda grammar" to make it easier to grep|sort sections.
Rhed Jao5377d792020-07-16 17:37:39 +08003860 dprintf(duration_fd_, "------ %.3fs was the duration of '%s' ------\n",
3861 elapsed, title_.c_str());
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003862 }
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003863 if (title_.find("SHOW MAP") == std::string::npos) {
3864 ATRACE_ASYNC_END(title_.c_str(), 0);
3865 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003866 }
3867}
3868
3869const int32_t Progress::kDefaultMax = 5000;
3870
3871Progress::Progress(const std::string& path) : Progress(Progress::kDefaultMax, 1.1, path) {
3872}
3873
3874Progress::Progress(int32_t initial_max, int32_t progress, float growth_factor)
3875 : Progress(initial_max, growth_factor, "") {
3876 progress_ = progress;
3877}
3878
3879Progress::Progress(int32_t initial_max, float growth_factor, const std::string& path)
3880 : initial_max_(initial_max),
3881 progress_(0),
3882 max_(initial_max),
3883 growth_factor_(growth_factor),
3884 n_runs_(0),
3885 average_max_(0),
3886 path_(path) {
3887 if (!path_.empty()) {
3888 Load();
3889 }
3890}
3891
3892void Progress::Load() {
3893 MYLOGD("Loading stats from %s\n", path_.c_str());
3894 std::string content;
3895 if (!android::base::ReadFileToString(path_, &content)) {
3896 MYLOGI("Could not read stats from %s; using max of %d\n", path_.c_str(), max_);
3897 return;
3898 }
3899 if (content.empty()) {
3900 MYLOGE("No stats (empty file) on %s; using max of %d\n", path_.c_str(), max_);
3901 return;
3902 }
3903 std::vector<std::string> lines = android::base::Split(content, "\n");
3904
3905 if (lines.size() < 1) {
3906 MYLOGE("Invalid stats on file %s: not enough lines (%d). Using max of %d\n", path_.c_str(),
3907 (int)lines.size(), max_);
3908 return;
3909 }
3910 char* ptr;
3911 n_runs_ = strtol(lines[0].c_str(), &ptr, 10);
3912 average_max_ = strtol(ptr, nullptr, 10);
3913 if (n_runs_ <= 0 || average_max_ <= 0 || n_runs_ > STATS_MAX_N_RUNS ||
3914 average_max_ > STATS_MAX_AVERAGE) {
3915 MYLOGE("Invalid stats line on file %s: %s\n", path_.c_str(), lines[0].c_str());
3916 initial_max_ = Progress::kDefaultMax;
3917 } else {
3918 initial_max_ = average_max_;
3919 }
3920 max_ = initial_max_;
3921
3922 MYLOGI("Average max progress: %d in %d runs; estimated max: %d\n", average_max_, n_runs_, max_);
3923}
3924
3925void Progress::Save() {
3926 int32_t total = n_runs_ * average_max_ + progress_;
3927 int32_t runs = n_runs_ + 1;
3928 int32_t average = floor(((float)total) / runs);
3929 MYLOGI("Saving stats (total=%d, runs=%d, average=%d) on %s\n", total, runs, average,
3930 path_.c_str());
3931 if (path_.empty()) {
3932 return;
3933 }
3934
3935 std::string content = android::base::StringPrintf("%d %d\n", runs, average);
3936 if (!android::base::WriteStringToFile(content, path_)) {
3937 MYLOGE("Could not save stats on %s\n", path_.c_str());
3938 }
3939}
3940
3941int32_t Progress::Get() const {
3942 return progress_;
3943}
3944
3945bool Progress::Inc(int32_t delta_sec) {
3946 bool changed = false;
3947 if (delta_sec >= 0) {
3948 progress_ += delta_sec;
3949 if (progress_ > max_) {
3950 int32_t old_max = max_;
3951 max_ = floor((float)progress_ * growth_factor_);
3952 MYLOGD("Adjusting max progress from %d to %d\n", old_max, max_);
3953 changed = true;
3954 }
3955 }
3956 return changed;
3957}
3958
3959int32_t Progress::GetMax() const {
3960 return max_;
3961}
3962
3963int32_t Progress::GetInitialMax() const {
3964 return initial_max_;
3965}
3966
3967void Progress::Dump(int fd, const std::string& prefix) const {
3968 const char* pr = prefix.c_str();
3969 dprintf(fd, "%sprogress: %d\n", pr, progress_);
3970 dprintf(fd, "%smax: %d\n", pr, max_);
3971 dprintf(fd, "%sinitial_max: %d\n", pr, initial_max_);
3972 dprintf(fd, "%sgrowth_factor: %0.2f\n", pr, growth_factor_);
3973 dprintf(fd, "%spath: %s\n", pr, path_.c_str());
3974 dprintf(fd, "%sn_runs: %d\n", pr, n_runs_);
3975 dprintf(fd, "%saverage_max: %d\n", pr, average_max_);
3976}
3977
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003978std::string Dumpstate::GetPath(const std::string& suffix) const {
3979 return GetPath(bugreport_internal_dir_, suffix);
3980}
3981
3982std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
3983 return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
3984 name_.c_str(), suffix.c_str());
3985}
3986
3987void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
3988 progress_ = std::move(progress);
3989}
3990
3991void for_each_userid(void (*func)(int), const char *header) {
3992 std::string title = header == nullptr ? "for_each_userid" : android::base::StringPrintf(
3993 "for_each_userid(%s)", header);
3994 DurationReporter duration_reporter(title);
3995 if (PropertiesHelper::IsDryRun()) return;
3996
3997 DIR *d;
3998 struct dirent *de;
3999
4000 if (header) printf("\n------ %s ------\n", header);
4001 func(0);
4002
4003 if (!(d = opendir("/data/system/users"))) {
4004 printf("Failed to open /data/system/users (%s)\n", strerror(errno));
4005 return;
4006 }
4007
4008 while ((de = readdir(d))) {
4009 int userid;
4010 if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
4011 continue;
4012 }
4013 func(userid);
4014 }
4015
4016 closedir(d);
4017}
4018
4019static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
4020 DIR *d;
4021 struct dirent *de;
4022
4023 if (!(d = opendir("/proc"))) {
4024 printf("Failed to open /proc (%s)\n", strerror(errno));
4025 return;
4026 }
4027
4028 if (header) printf("\n------ %s ------\n", header);
4029 while ((de = readdir(d))) {
4030 if (ds.IsUserConsentDenied()) {
4031 MYLOGE(
4032 "Returning early because user denied consent to share bugreport with calling app.");
4033 closedir(d);
4034 return;
4035 }
4036 int pid;
4037 int fd;
4038 char cmdpath[255];
4039 char cmdline[255];
4040
4041 if (!(pid = atoi(de->d_name))) {
4042 continue;
4043 }
4044
4045 memset(cmdline, 0, sizeof(cmdline));
4046
4047 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
4048 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
4049 TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
4050 close(fd);
4051 if (cmdline[0]) {
4052 helper(pid, cmdline, arg);
4053 continue;
4054 }
4055 }
4056
4057 // if no cmdline, a kernel thread has comm
4058 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
4059 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
4060 TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
4061 close(fd);
4062 if (cmdline[1]) {
4063 cmdline[0] = '[';
4064 size_t len = strcspn(cmdline, "\f\b\r\n");
4065 cmdline[len] = ']';
4066 cmdline[len+1] = '\0';
4067 }
4068 }
4069 if (!cmdline[0]) {
4070 strcpy(cmdline, "N/A");
4071 }
4072 helper(pid, cmdline, arg);
4073 }
4074
4075 closedir(d);
4076}
4077
4078static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
4079 for_each_pid_func *func = (for_each_pid_func*) arg;
4080 func(pid, cmdline);
4081}
4082
4083void for_each_pid(for_each_pid_func func, const char *header) {
4084 std::string title = header == nullptr ? "for_each_pid"
4085 : android::base::StringPrintf("for_each_pid(%s)", header);
4086 DurationReporter duration_reporter(title);
4087 if (PropertiesHelper::IsDryRun()) return;
4088
4089 __for_each_pid(for_each_pid_helper, header, (void *) func);
4090}
4091
4092static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
4093 DIR *d;
4094 struct dirent *de;
4095 char taskpath[255];
4096 for_each_tid_func *func = (for_each_tid_func *) arg;
4097
4098 snprintf(taskpath, sizeof(taskpath), "/proc/%d/task", pid);
4099
4100 if (!(d = opendir(taskpath))) {
4101 printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
4102 return;
4103 }
4104
4105 func(pid, pid, cmdline);
4106
4107 while ((de = readdir(d))) {
4108 if (ds.IsUserConsentDenied()) {
4109 MYLOGE(
4110 "Returning early because user denied consent to share bugreport with calling app.");
4111 closedir(d);
4112 return;
4113 }
4114 int tid;
4115 int fd;
4116 char commpath[255];
4117 char comm[255];
4118
4119 if (!(tid = atoi(de->d_name))) {
4120 continue;
4121 }
4122
4123 if (tid == pid)
4124 continue;
4125
4126 snprintf(commpath, sizeof(commpath), "/proc/%d/comm", tid);
4127 memset(comm, 0, sizeof(comm));
4128 if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
4129 strcpy(comm, "N/A");
4130 } else {
4131 char *c;
4132 TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
4133 close(fd);
4134
4135 c = strrchr(comm, '\n');
4136 if (c) {
4137 *c = '\0';
4138 }
4139 }
4140 func(pid, tid, comm);
4141 }
4142
4143 closedir(d);
4144}
4145
4146void for_each_tid(for_each_tid_func func, const char *header) {
4147 std::string title = header == nullptr ? "for_each_tid"
4148 : android::base::StringPrintf("for_each_tid(%s)", header);
4149 DurationReporter duration_reporter(title);
4150
4151 if (PropertiesHelper::IsDryRun()) return;
4152
4153 __for_each_pid(for_each_tid_helper, header, (void *) func);
4154}
4155
4156void show_wchan(int pid, int tid, const char *name) {
4157 if (PropertiesHelper::IsDryRun()) return;
4158
4159 char path[255];
4160 char buffer[255];
4161 int fd, ret, save_errno;
4162 char name_buffer[255];
4163
4164 memset(buffer, 0, sizeof(buffer));
4165
4166 snprintf(path, sizeof(path), "/proc/%d/wchan", tid);
4167 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
4168 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
4169 return;
4170 }
4171
4172 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
4173 save_errno = errno;
4174 close(fd);
4175
4176 if (ret < 0) {
4177 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
4178 return;
4179 }
4180
4181 snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
4182 pid == tid ? 0 : 3, "", name);
4183
4184 printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
4185
4186 return;
4187}
4188
4189// print time in centiseconds
4190static void snprcent(char *buffer, size_t len, size_t spc,
4191 unsigned long long time) {
4192 static long hz; // cache discovered hz
4193
4194 if (hz <= 0) {
4195 hz = sysconf(_SC_CLK_TCK);
4196 if (hz <= 0) {
4197 hz = 1000;
4198 }
4199 }
4200
4201 // convert to centiseconds
4202 time = (time * 100 + (hz / 2)) / hz;
4203
4204 char str[16];
4205
4206 snprintf(str, sizeof(str), " %llu.%02u",
4207 time / 100, (unsigned)(time % 100));
4208 size_t offset = strlen(buffer);
4209 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
4210 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
4211}
4212
4213// print permille as a percent
4214static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
4215 char str[16];
4216
4217 snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
4218 size_t offset = strlen(buffer);
4219 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
4220 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
4221}
4222
4223void show_showtime(int pid, const char *name) {
4224 if (PropertiesHelper::IsDryRun()) return;
4225
4226 char path[255];
4227 char buffer[1023];
4228 int fd, ret, save_errno;
4229
4230 memset(buffer, 0, sizeof(buffer));
4231
4232 snprintf(path, sizeof(path), "/proc/%d/stat", pid);
4233 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
4234 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
4235 return;
4236 }
4237
4238 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
4239 save_errno = errno;
4240 close(fd);
4241
4242 if (ret < 0) {
4243 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
4244 return;
4245 }
4246
4247 // field 14 is utime
4248 // field 15 is stime
4249 // field 42 is iotime
4250 unsigned long long utime = 0, stime = 0, iotime = 0;
4251 if (sscanf(buffer,
4252 "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
4253 "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
4254 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
4255 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
4256 &utime, &stime, &iotime) != 3) {
4257 return;
4258 }
4259
4260 unsigned long long total = utime + stime;
4261 if (!total) {
4262 return;
4263 }
4264
4265 unsigned permille = (iotime * 1000 + (total / 2)) / total;
4266 if (permille > 1000) {
4267 permille = 1000;
4268 }
4269
4270 // try to beautify and stabilize columns at <80 characters
4271 snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
4272 if ((name[0] != '[') || utime) {
4273 snprcent(buffer, sizeof(buffer), 57, utime);
4274 }
4275 snprcent(buffer, sizeof(buffer), 65, stime);
4276 if ((name[0] != '[') || iotime) {
4277 snprcent(buffer, sizeof(buffer), 73, iotime);
4278 }
4279 if (iotime) {
4280 snprdec(buffer, sizeof(buffer), 79, permille);
4281 }
4282 puts(buffer); // adds a trailing newline
4283
4284 return;
4285}
4286
4287void do_dmesg() {
4288 const char *title = "KERNEL LOG (dmesg)";
4289 DurationReporter duration_reporter(title);
4290 printf("------ %s ------\n", title);
4291
4292 if (PropertiesHelper::IsDryRun()) return;
4293
4294 /* Get size of kernel buffer */
4295 int size = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
4296 if (size <= 0) {
4297 printf("Unexpected klogctl return value: %d\n\n", size);
4298 return;
4299 }
4300 char *buf = (char *) malloc(size + 1);
4301 if (buf == nullptr) {
4302 printf("memory allocation failed\n\n");
4303 return;
4304 }
4305 int retval = klogctl(KLOG_READ_ALL, buf, size);
4306 if (retval < 0) {
4307 printf("klogctl failure\n\n");
4308 free(buf);
4309 return;
4310 }
4311 buf[retval] = '\0';
4312 printf("%s\n\n", buf);
4313 free(buf);
4314 return;
4315}
4316
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004317int Dumpstate::DumpFile(const std::string& title, const std::string& path) {
4318 DurationReporter duration_reporter(title);
4319
4320 int status = DumpFileToFd(STDOUT_FILENO, title, path);
4321
4322 UpdateProgress(WEIGHT_FILE);
4323
4324 return status;
4325}
4326
4327int read_file_as_long(const char *path, long int *output) {
luoqiangwei15fcf2022024-03-07 15:29:20 +08004328 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
4329 if (fd.get() < 0) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004330 int err = errno;
4331 MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
4332 return -1;
4333 }
4334 char buffer[50];
luoqiangwei15fcf2022024-03-07 15:29:20 +08004335 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer, sizeof(buffer)));
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004336 if (bytes_read == -1) {
4337 MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
4338 return -2;
4339 }
4340 if (bytes_read == 0) {
4341 MYLOGE("File %s is empty\n", path);
4342 return -3;
4343 }
4344 *output = atoi(buffer);
4345 return 0;
4346}
4347
4348/* calls skip to gate calling dump_from_fd recursively
4349 * in the specified directory. dump_from_fd defaults to
4350 * dump_file_from_fd above when set to NULL. skip defaults
4351 * to false when set to NULL. dump_from_fd will always be
4352 * called with title NULL.
4353 */
4354int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
4355 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4356 DurationReporter duration_reporter(title);
4357 DIR *dirp;
4358 struct dirent *d;
4359 char *newpath = nullptr;
4360 const char *slash = "/";
4361 int retval = 0;
4362
4363 if (!title.empty()) {
4364 printf("------ %s (%s) ------\n", title.c_str(), dir);
4365 }
4366 if (PropertiesHelper::IsDryRun()) return 0;
4367
4368 if (dir[strlen(dir) - 1] == '/') {
4369 ++slash;
4370 }
4371 dirp = opendir(dir);
4372 if (dirp == nullptr) {
4373 retval = -errno;
4374 MYLOGE("%s: %s\n", dir, strerror(errno));
4375 return retval;
4376 }
4377
4378 if (!dump_from_fd) {
4379 dump_from_fd = dump_file_from_fd;
4380 }
4381 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4382 if ((d->d_name[0] == '.')
4383 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4384 || (d->d_name[1] == '\0'))) {
4385 continue;
4386 }
4387 asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
4388 (d->d_type == DT_DIR) ? "/" : "");
4389 if (!newpath) {
4390 retval = -errno;
4391 continue;
4392 }
4393 if (skip && (*skip)(newpath)) {
4394 continue;
4395 }
4396 if (d->d_type == DT_DIR) {
4397 int ret = dump_files("", newpath, skip, dump_from_fd);
4398 if (ret < 0) {
4399 retval = ret;
4400 }
4401 continue;
4402 }
4403 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
4404 if (fd.get() < 0) {
4405 retval = -1;
4406 printf("*** %s: %s\n", newpath, strerror(errno));
4407 continue;
4408 }
4409 (*dump_from_fd)(nullptr, newpath, fd.get());
4410 }
4411 closedir(dirp);
4412 if (!title.empty()) {
4413 printf("\n");
4414 }
4415 return retval;
4416}
4417
4418/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
4419 * it's possible to avoid issues where opening the file itself can get
4420 * stuck.
4421 */
4422int dump_file_from_fd(const char *title, const char *path, int fd) {
4423 if (PropertiesHelper::IsDryRun()) return 0;
4424
4425 int flags = fcntl(fd, F_GETFL);
4426 if (flags == -1) {
4427 printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
4428 return -1;
4429 } else if (!(flags & O_NONBLOCK)) {
4430 printf("*** %s: fd must have O_NONBLOCK set.\n", path);
4431 return -1;
4432 }
4433 return DumpFileFromFdToFd(title, path, fd, STDOUT_FILENO, PropertiesHelper::IsDryRun());
4434}
4435
4436int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004437 const CommandOptions& options, bool verbose_duration, int out_fd) {
4438 DurationReporter duration_reporter(title, false /* logcat_only */,
4439 verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004440
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004441 int status = RunCommandToFd(out_fd, title, full_command, options);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004442
4443 /* TODO: for now we're simplifying the progress calculation by using the
4444 * timeout as the weight. It's a good approximation for most cases, except when calling dumpsys,
4445 * where its weight should be much higher proportionally to its timeout.
4446 * Ideally, it should use a options.EstimatedDuration() instead...*/
4447 UpdateProgress(options.Timeout());
4448
4449 return status;
4450}
4451
4452void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
Rhed Jaoe017f982020-07-21 17:58:41 +08004453 const CommandOptions& options, long dumpsysTimeoutMs, int out_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004454 long timeout_ms = dumpsysTimeoutMs > 0 ? dumpsysTimeoutMs : options.TimeoutInMs();
4455 std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-T", std::to_string(timeout_ms)};
4456 dumpsys.insert(dumpsys.end(), dumpsys_args.begin(), dumpsys_args.end());
Rhed Jaoe017f982020-07-21 17:58:41 +08004457 RunCommand(title, dumpsys, options, false, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004458}
4459
Dieter Hsu105ad0c2020-09-29 15:23:33 +08004460static int open_socket(const char* service) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004461 int s = android_get_control_socket(service);
4462 if (s < 0) {
4463 MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
4464 return -1;
4465 }
4466 fcntl(s, F_SETFD, FD_CLOEXEC);
4467
4468 // Set backlog to 0 to make sure that queue size will be minimum.
4469 // In Linux, because the minimum queue will be 1, connect() will be blocked
4470 // if the other clients already called connect() and the connection request was not accepted.
4471 if (listen(s, 0) < 0) {
4472 MYLOGE("listen(control socket): %s\n", strerror(errno));
4473 return -1;
4474 }
4475
4476 struct sockaddr addr;
4477 socklen_t alen = sizeof(addr);
Abhijeet Kaur2113cae2019-09-13 09:24:15 +01004478 int fd = accept4(s, &addr, &alen, SOCK_CLOEXEC);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004479
4480 // Close socket just after accept(), to make sure that connect() by client will get error
4481 // when the socket is used by the other services.
4482 // There is still a race condition possibility between accept and close, but there is no way
4483 // to close-on-accept atomically.
4484 // See detail; b/123306389#comment25
4485 close(s);
4486
4487 if (fd < 0) {
4488 MYLOGE("accept(control socket): %s\n", strerror(errno));
4489 return -1;
4490 }
4491
4492 return fd;
4493}
4494
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004495// TODO: should call is_valid_output_file and/or be merged into it.
4496void create_parent_dirs(const char *path) {
4497 char *chp = const_cast<char *> (path);
4498
4499 /* skip initial slash */
4500 if (chp[0] == '/')
4501 chp++;
4502
4503 /* create leading directories, if necessary */
4504 struct stat dir_stat;
4505 while (chp && chp[0]) {
4506 chp = strchr(chp, '/');
4507 if (chp) {
4508 *chp = 0;
4509 if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
4510 MYLOGI("Creating directory %s\n", path);
4511 if (mkdir(path, 0770)) { /* drwxrwx--- */
4512 MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
4513 } else if (chown(path, AID_SHELL, AID_SHELL)) {
4514 MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
4515 }
4516 }
4517 *chp++ = '/';
4518 }
4519 }
4520}
4521
4522bool _redirect_to_file(FILE* redirect, char* path, int truncate_flag) {
4523 create_parent_dirs(path);
4524
4525 int fd = TEMP_FAILURE_RETRY(open(path,
4526 O_WRONLY | O_CREAT | truncate_flag | O_CLOEXEC | O_NOFOLLOW,
4527 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
4528 if (fd < 0) {
4529 MYLOGE("%s: %s\n", path, strerror(errno));
4530 return false;
4531 }
4532
4533 TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
4534 close(fd);
4535 return true;
4536}
4537
4538bool redirect_to_file(FILE* redirect, char* path) {
4539 return _redirect_to_file(redirect, path, O_TRUNC);
4540}
4541
4542bool redirect_to_existing_file(FILE* redirect, char* path) {
4543 return _redirect_to_file(redirect, path, O_APPEND);
4544}
4545
4546void dump_route_tables() {
4547 DurationReporter duration_reporter("DUMP ROUTE TABLES");
4548 if (PropertiesHelper::IsDryRun()) return;
4549 const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
4550 ds.DumpFile("RT_TABLES", RT_TABLES_PATH);
4551 FILE* fp = fopen(RT_TABLES_PATH, "re");
4552 if (!fp) {
4553 printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
4554 return;
4555 }
4556 char table[16];
4557 // Each line has an integer (the table number), a space, and a string (the table name). We only
4558 // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
4559 // Add a fixed max limit so this doesn't go awry.
4560 for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
4561 RunCommand("ROUTE TABLE IPv4", {"ip", "-4", "route", "show", "table", table});
4562 RunCommand("ROUTE TABLE IPv6", {"ip", "-6", "route", "show", "table", table});
4563 }
4564 fclose(fp);
4565}
4566
Li Li830179f2022-01-04 12:53:29 -08004567void dump_frozen_cgroupfs(const char *dir, int level,
4568 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4569 DIR *dirp;
4570 struct dirent *d;
4571 char *newpath = nullptr;
4572
4573 dirp = opendir(dir);
4574 if (dirp == nullptr) {
4575 MYLOGE("%s: %s\n", dir, strerror(errno));
4576 return;
4577 }
4578
4579 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4580 if ((d->d_name[0] == '.')
4581 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4582 || (d->d_name[1] == '\0'))) {
4583 continue;
4584 }
4585 if (d->d_type == DT_DIR) {
4586 asprintf(&newpath, "%s/%s/", dir, d->d_name);
4587 if (!newpath) {
4588 continue;
4589 }
4590 if (level == 0 && !strncmp(d->d_name, "uid_", 4)) {
4591 dump_frozen_cgroupfs(newpath, 1, dump_from_fd);
4592 } else if (level == 1 && !strncmp(d->d_name, "pid_", 4)) {
4593 char *freezer = nullptr;
4594 asprintf(&freezer, "%s/%s", newpath, "cgroup.freeze");
4595 if (freezer) {
4596 FILE* fp = fopen(freezer, "r");
4597 if (fp != NULL) {
4598 int frozen;
4599 fscanf(fp, "%d", &frozen);
4600 if (frozen > 0) {
4601 dump_files("", newpath, skip_none, dump_from_fd);
4602 }
4603 fclose(fp);
4604 }
4605 free(freezer);
4606 }
4607 }
4608 }
4609 }
4610 closedir(dirp);
4611}
4612
4613void dump_frozen_cgroupfs() {
Li Li830179f2022-01-04 12:53:29 -08004614 MYLOGD("Adding frozen processes from %s\n", CGROUPFS_DIR);
4615 DurationReporter duration_reporter("FROZEN CGROUPFS");
4616 if (PropertiesHelper::IsDryRun()) return;
4617 dump_frozen_cgroupfs(CGROUPFS_DIR, 0, _add_file_from_fd);
4618}
4619
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004620void Dumpstate::UpdateProgress(int32_t delta_sec) {
4621 if (progress_ == nullptr) {
4622 MYLOGE("UpdateProgress: progress_ not set\n");
4623 return;
4624 }
Rhed Jaobf63d8a2020-07-21 15:42:55 +08004625 // This function updates progress related members of the dumpstate and reports
4626 // progress percentage to the bugreport client. Since it could be called by
4627 // different dump tasks at the same time if the parallel run is enabled, a
4628 // mutex lock is necessary here to synchronize the call.
4629 std::lock_guard<std::recursive_mutex> lock(mutex_);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004630
4631 // Always update progess so stats can be tuned...
Nandana Dutt402a8392019-06-14 14:25:13 +01004632 progress_->Inc(delta_sec);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004633
4634 // ...but only notifiy listeners when necessary.
4635 if (!options_->do_progress_updates) return;
4636
4637 int progress = progress_->Get();
4638 int max = progress_->GetMax();
Nandana Dutt402a8392019-06-14 14:25:13 +01004639 int percent = 100 * progress / max;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004640
Nandana Dutt402a8392019-06-14 14:25:13 +01004641 if (last_reported_percent_progress_ > 0 && percent <= last_reported_percent_progress_) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004642 return;
4643 }
Nandana Dutt402a8392019-06-14 14:25:13 +01004644 last_reported_percent_progress_ = percent;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004645
4646 if (control_socket_fd_ >= 0) {
4647 dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
4648 fsync(control_socket_fd_);
4649 }
4650
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004651 if (listener_ != nullptr) {
Nandana Dutt235c6672019-11-14 15:22:32 +00004652 if (percent % 10 == 0) {
4653 // We don't want to spam logcat, so only log multiples of 10.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004654 MYLOGD("Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004655 } else {
4656 // stderr is ignored on normal invocations, but useful when calling
4657 // /system/bin/dumpstate directly for debuggging.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004658 fprintf(stderr, "Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004659 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004660
4661 listener_->onProgress(percent);
4662 }
4663}
4664
4665void Dumpstate::TakeScreenshot(const std::string& path) {
4666 const std::string& real_path = path.empty() ? screenshot_path_ : path;
4667 int status =
Abdelrahman Daim30e23602024-08-20 02:19:37 -07004668 RunCommand("", {"screencap", "-p", real_path},
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004669 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
4670 if (status == 0) {
4671 MYLOGD("Screenshot saved on %s\n", real_path.c_str());
4672 } else {
4673 MYLOGE("Failed to take screenshot on %s\n", real_path.c_str());
4674 }
Paul Chang0d2aad72020-02-13 20:04:03 +08004675 if (listener_ != nullptr) {
4676 // Show a visual indication to indicate screenshot is taken via
4677 // IDumpstateListener.onScreenshotTaken()
4678 listener_->onScreenshotTaken(status == 0);
4679 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004680}
4681
4682bool is_dir(const char* pathname) {
4683 struct stat info;
4684 if (stat(pathname, &info) == -1) {
4685 return false;
4686 }
4687 return S_ISDIR(info.st_mode);
4688}
4689
4690time_t get_mtime(int fd, time_t default_mtime) {
4691 struct stat info;
4692 if (fstat(fd, &info) == -1) {
4693 return default_mtime;
4694 }
4695 return info.st_mtime;
4696}