blob: c407f486f09be56ec736979123a6d46bd8e028ca [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
Abhijeet Kaurcf234e82019-07-01 14:53:55 +0100131// Keep in sync with
132// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
133static const int TRACE_DUMP_TIMEOUT_MS = 10000; // 10 seconds
134
135/* Most simple commands have 10 as timeout, so 5 is a good estimate */
136static const int32_t WEIGHT_FILE = 5;
137
138// TODO: temporary variables and functions used during C++ refactoring
139static Dumpstate& ds = Dumpstate::GetInstance();
140static int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Nandana Dutt8d945c02019-08-14 13:30:07 +0100141 const CommandOptions& options = CommandOptions::DEFAULT,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800142 bool verbose_duration = false, int out_fd = STDOUT_FILENO) {
143 return ds.RunCommand(title, full_command, options, verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +0100144}
145
146// Reasonable value for max stats.
147static const int STATS_MAX_N_RUNS = 1000;
148static const long STATS_MAX_AVERAGE = 100000;
149
150CommandOptions Dumpstate::DEFAULT_DUMPSYS = CommandOptions::WithTimeout(30).Build();
151
Nandana Duttd2f5f082019-01-18 17:13:52 +0000152typedef Dumpstate::ConsentCallback::ConsentResult UserConsentResult;
153
Colin Crossf45fa6b2012-03-26 12:38:26 -0700154/* read before root is shed */
155static char cmdline_buf[16384] = "(unknown)";
Yi Kong19d5c002018-07-20 13:39:55 -0700156static const char *dump_traces_path = nullptr;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000157static const uint64_t USER_CONSENT_TIMEOUT_MS = 30 * 1000;
Hunter Knepshield70610fa2020-01-03 15:27:33 -0800158// Because telephony reports are significantly faster to collect (< 10 seconds vs. > 2 minutes),
159// it's often the case that they time out far too quickly for consent with such a hefty dialog for
160// the user to read. For telephony reports only, we increase the default timeout to 2 minutes to
161// roughly match full reports' durations.
162static const uint64_t TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS = 2 * 60 * 1000;
Colin Crossf45fa6b2012-03-26 12:38:26 -0700163
Felipe Leme1d486fe2016-10-14 18:06:47 -0700164// TODO: variables and functions below should be part of dumpstate object
165
Felipe Leme635ca312016-01-05 14:23:02 -0800166static std::set<std::string> mount_points;
167void add_mountinfo();
Felipe Leme78f2c862015-12-21 09:55:22 -0800168
Todd Poynor2a83daa2013-11-22 15:44:22 -0800169#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
Mark Salyzyn7d0a7622016-06-24 14:06:15 -0700170#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
Wei Wang509bb5d2017-06-09 14:42:12 -0700171#define BLK_DEV_SYS_DIR "/sys/block"
Todd Poynor2a83daa2013-11-22 15:44:22 -0800172
Ted Bauerf6d61b82024-09-13 19:57:19 +0000173#define AFLAGS "/system/bin/aflags"
Felipe Lemee82a27d2016-01-05 13:35:44 -0800174#define RECOVERY_DIR "/cache/recovery"
Mark Salyzynd6ab0112016-03-25 12:56:39 -0700175#define RECOVERY_DATA_DIR "/data/misc/recovery"
Tianjie Xu75d53362018-04-11 16:42:28 -0700176#define UPDATE_ENGINE_LOG_DIR "/data/misc/update_engine_log"
Kelvin Zhang6eaa0f92022-09-12 09:29:19 -0700177#define UPDATE_ENGINE_PREF_DIR "/data/misc/update_engine/prefs"
Mark Salyzyn4d42dea2016-04-01 10:03:14 -0700178#define LOGPERSIST_DATA_DIR "/data/misc/logd"
Jerry Changa1df8a92020-01-02 16:03:39 +0800179#define PREREBOOT_DATA_DIR "/data/misc/prereboot"
David Brazdild2991962016-06-03 14:40:44 +0100180#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
181#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
Benedict Wong8f9d8a42019-01-03 16:19:38 -0800182#define XFRM_STAT_PROC_FILE "/proc/net/xfrm_stat"
Steven Moreland9379c462023-12-21 02:04:27 +0000183#define KERNEL_CONFIG "/proc/config.gz"
Erik Kline08165202016-05-30 11:55:44 +0900184#define WLUTIL "/vendor/xbin/wlutil"
Vishnu Nair36b4cdb2017-11-17 10:27:05 -0800185#define WMTRACE_DATA_DIR "/data/misc/wmtrace"
Yifan Hong3945e1b2019-10-29 12:59:23 -0700186#define OTA_METADATA_DIR "/metadata/ota"
Yifan Hong0efa7972020-02-03 16:45:02 -0800187#define SNAPSHOTCTL_LOG_DIR "/data/misc/snapshotctl_log"
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +0900188#define LINKERCONFIG_DIR "/linkerconfig"
Calin Juravlef84d3692020-04-28 15:31:12 -0700189#define PACKAGE_DEX_USE_LIST "/data/system/package-dex-usage.list"
Primiano Tuccifaaaafb2021-01-14 12:26:29 +0000190#define SYSTEM_TRACE_SNAPSHOT "/data/misc/perfetto-traces/bugreport/systrace.pftrace"
Li Li2eedd412021-06-30 15:11:53 -0700191#define CGROUPFS_DIR "/sys/fs/cgroup"
MÃ¥rten Kongstad60195a72022-09-20 14:14:20 +0200192#define SDK_EXT_INFO "/apex/com.android.sdkext/bin/derive_sdk"
Jeff Sharkey9df29d52023-02-06 14:26:30 -0700193#define DROPBOX_DIR "/data/system/dropbox"
MÃ¥rten Kongstad5ad813f2023-09-28 10:09:18 +0200194#define PRINT_FLAGS "/system/bin/printflags"
Nattharat Jariyanuntanaetb250cae2024-05-15 07:48:19 +0000195#define UWB_LOG_DIR "/data/misc/apexdata/com.android.uwb/log"
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700196
Narayan Kamath8f788292017-05-25 13:20:39 +0100197// TODO(narayan): Since this information has to be kept in sync
198// with tombstoned, we should just put it in a common header.
199//
200// File: system/core/debuggerd/tombstoned/tombstoned.cpp
Narayan Kamathbd863722017-06-01 18:50:12 +0100201static const std::string TOMBSTONE_DIR = "/data/tombstones/";
202static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
203static const std::string ANR_DIR = "/data/anr/";
204static const std::string ANR_FILE_PREFIX = "anr_";
Andy Hungd62f7e62024-01-11 15:47:52 -0800205static const std::string ANR_TRACE_FILE_PREFIX = "trace_";
Woody Lin20767a92022-11-29 15:50:24 +0800206static const std::string SHUTDOWN_CHECKPOINTS_DIR = "/data/system/shutdown-checkpoints/";
207static const std::string SHUTDOWN_CHECKPOINTS_FILE_PREFIX = "checkpoints-";
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700208
Felipe Lemee844a9d2016-09-21 15:01:39 -0700209// TODO: temporary variables and functions used during C++ refactoring
Nandana Dutt979388e2018-11-30 16:48:55 +0000210
Nandana Dutt5c390032019-03-12 10:52:56 +0000211#define RETURN_IF_USER_DENIED_CONSENT() \
212 if (ds.IsUserConsentDenied()) { \
213 MYLOGE("Returning early as user denied consent to share bugreport with calling app."); \
214 return Dumpstate::RunStatus::USER_CONSENT_DENIED; \
215 }
216
217// Runs func_ptr, but checks user consent before and after running it. Returns USER_CONSENT_DENIED
218// if consent is found to be denied.
219#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(func_ptr, ...) \
220 RETURN_IF_USER_DENIED_CONSENT(); \
221 func_ptr(__VA_ARGS__); \
222 RETURN_IF_USER_DENIED_CONSENT();
223
Rhed Jao5377d792020-07-16 17:37:39 +0800224// Runs func_ptr, and logs a duration report after it's finished.
225#define RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, ...) \
226 { \
227 DurationReporter duration_reporter_in_macro(log_title); \
228 func_ptr(__VA_ARGS__); \
229 }
230
231// Similar with RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK, an additional duration report
232// is output after a slow function is finished.
233#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(log_title, func_ptr, ...) \
234 RETURN_IF_USER_DENIED_CONSENT(); \
235 RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, __VA_ARGS__); \
236 RETURN_IF_USER_DENIED_CONSENT();
237
Chris Morinbc223142022-02-04 14:17:11 -0800238#define WAIT_TASK_WITH_CONSENT_CHECK(future) \
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800239 RETURN_IF_USER_DENIED_CONSENT(); \
Chris Morinbc223142022-02-04 14:17:11 -0800240 WaitForTask(future); \
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800241 RETURN_IF_USER_DENIED_CONSENT();
242
Sahana Raof35ed432019-07-12 10:47:52 +0100243static const char* WAKE_LOCK_NAME = "dumpstate_wakelock";
244
Rhed Jao5377d792020-07-16 17:37:39 +0800245// Names of parallel tasks, they are used for the DumpPool to identify the dump
246// task and the log title of the duration report.
247static const std::string DUMP_TRACES_TASK = "DUMP TRACES";
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800248static const std::string DUMP_INCIDENT_REPORT_TASK = "INCIDENT REPORT";
Aaron Huang24d215d2022-04-27 18:51:16 +0800249static const std::string DUMP_NETSTATS_PROTO_TASK = "DUMP NETSTATS PROTO";
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800250static const std::string DUMP_HALS_TASK = "DUMP HALS";
251static const std::string DUMP_BOARD_TASK = "dumpstate_board()";
Rhed Jaoe017f982020-07-21 17:58:41 +0800252static const std::string DUMP_CHECKINS_TASK = "DUMP CHECKINS";
Kean Mariottica20f2d2023-12-15 09:34:25 +0000253static const std::string SERIALIZE_PERFETTO_TRACE_TASK = "SERIALIZE PERFETTO TRACE";
Rhed Jao5377d792020-07-16 17:37:39 +0800254
Nandana Dutt979388e2018-11-30 16:48:55 +0000255namespace android {
256namespace os {
257namespace {
258
259static int Open(std::string path, int flags, mode_t mode = 0) {
260 int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
261 if (fd == -1) {
262 MYLOGE("open(%s, %s)\n", path.c_str(), strerror(errno));
263 }
264 return fd;
265}
266
mhasank2d75c442020-06-11 15:05:25 -0700267static int OpenForWrite(std::string path) {
268 return Open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
269 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
270}
Nandana Dutt979388e2018-11-30 16:48:55 +0000271
272static int OpenForRead(std::string path) {
273 return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
274}
275
276bool CopyFile(int in_fd, int out_fd) {
277 char buf[4096];
278 ssize_t byte_count;
279 while ((byte_count = TEMP_FAILURE_RETRY(read(in_fd, buf, sizeof(buf)))) > 0) {
280 if (!android::base::WriteFully(out_fd, buf, byte_count)) {
281 return false;
282 }
283 }
284 return (byte_count != -1);
285}
286
287static bool CopyFileToFd(const std::string& input_file, int out_fd) {
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000288 MYLOGD("Going to copy file (%s) to %d\n", input_file.c_str(), out_fd);
Nandana Dutt979388e2018-11-30 16:48:55 +0000289
290 // Obtain a handle to the source file.
291 android::base::unique_fd in_fd(OpenForRead(input_file));
292 if (out_fd != -1 && in_fd.get() != -1) {
293 if (CopyFile(in_fd.get(), out_fd)) {
294 return true;
295 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000296 MYLOGE("Failed to copy file: %s\n", strerror(errno));
Nandana Dutt979388e2018-11-30 16:48:55 +0000297 }
298 return false;
299}
300
Nandana Duttd2f5f082019-01-18 17:13:52 +0000301static bool UnlinkAndLogOnError(const std::string& file) {
Nandana Dutt8ae16e62020-03-27 10:20:22 +0000302 if (file.empty()) {
303 return false;
304 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000305 if (unlink(file.c_str())) {
306 MYLOGE("Failed to unlink file (%s): %s\n", file.c_str(), strerror(errno));
Nandana Duttd2f5f082019-01-18 17:13:52 +0000307 return false;
308 }
309 return true;
310}
Nandana Dutt979388e2018-11-30 16:48:55 +0000311
Nikita Ioffea325a572019-05-16 19:49:47 +0100312int64_t GetModuleMetadataVersion() {
313 auto binder = defaultServiceManager()->getService(android::String16("package_native"));
314 if (binder == nullptr) {
315 MYLOGE("Failed to retrieve package_native service");
316 return 0L;
317 }
318 auto package_service = android::interface_cast<content::pm::IPackageManagerNative>(binder);
319 std::string package_name;
320 auto status = package_service->getModuleMetadataPackageName(&package_name);
321 if (!status.isOk()) {
322 MYLOGE("Failed to retrieve module metadata package name: %s", status.toString8().c_str());
323 return 0L;
324 }
Nandana Duttdb379fa2019-10-09 16:54:41 +0100325 MYLOGD("Module metadata package name: %s\n", package_name.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100326 int64_t version_code;
327 status = package_service->getVersionCodeForPackage(android::String16(package_name.c_str()),
328 &version_code);
329 if (!status.isOk()) {
330 MYLOGE("Failed to retrieve module metadata version: %s", status.toString8().c_str());
331 return 0L;
332 }
333 return version_code;
334}
335
mhasank2d75c442020-06-11 15:05:25 -0700336static bool PathExists(const std::string& path) {
337 struct stat sb;
338 return stat(path.c_str(), &sb) == 0;
339}
340
341static bool CopyFileToFile(const std::string& input_file, const std::string& output_file) {
342 if (input_file == output_file) {
343 MYLOGD("Skipping copying bugreport file since the destination is the same (%s)\n",
344 output_file.c_str());
345 return false;
346 }
347 else if (PathExists(output_file)) {
348 MYLOGD("Cannot overwrite an existing file (%s)\n", output_file.c_str());
349 return false;
350 }
351
352 MYLOGD("Going to copy bugreport file (%s) to %s\n", input_file.c_str(), output_file.c_str());
353 android::base::unique_fd out_fd(OpenForWrite(output_file));
354 return CopyFileToFd(input_file, out_fd.get());
355}
356
Nandana Dutt979388e2018-11-30 16:48:55 +0000357} // namespace
358} // namespace os
359} // namespace android
360
Felipe Leme678727a2016-09-21 17:22:11 -0700361static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
Felipe Lemebda15a02016-11-16 17:48:25 -0800362 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
Rhed Jaoe017f982020-07-21 17:58:41 +0800363 long dumpsysTimeoutMs = 0, int out_fd = STDOUT_FILENO) {
364 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs, out_fd);
365}
366static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
367 int out_fd) {
368 return ds.RunDumpsys(title, dumpsysArgs, Dumpstate::DEFAULT_DUMPSYS, 0, out_fd);
Felipe Leme678727a2016-09-21 17:22:11 -0700369}
370static int DumpFile(const std::string& title, const std::string& path) {
371 return ds.DumpFile(title, path);
372}
Felipe Lemee82a27d2016-01-05 13:35:44 -0800373
Felipe Lemee844a9d2016-09-21 15:01:39 -0700374// Relative directory (inside the zip) for all files copied as-is into the bugreport.
375static const std::string ZIP_ROOT_DIR = "FS";
376
Vishnu Naire97d6122018-01-18 13:58:56 -0800377static const std::string kProtoPath = "proto/";
378static const std::string kProtoExt = ".proto";
Jie Song9fbfad02017-06-20 16:29:42 -0700379static const std::string kDumpstateBoardFiles[] = {
380 "dumpstate_board.txt",
Felipe Leme95d6ca52017-08-01 16:35:56 -0700381 "dumpstate_board.bin"
Jie Song9fbfad02017-06-20 16:29:42 -0700382};
383static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
384
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700385static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Lemed071c682016-10-20 16:48:00 -0700386static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700387
Felipe Lemef0292972016-11-22 13:57:05 -0800388static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
389
Narayan Kamath8f788292017-05-25 13:20:39 +0100390/*
Narayan Kamathbd863722017-06-01 18:50:12 +0100391 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
Rhed Jao01dc0c62020-06-03 17:13:30 +0800392 * The returned vector is sorted by the mtimes of the dumps with descending
Chris Morinc2cba7a2022-02-01 17:06:50 -0800393 * order.
Narayan Kamath8f788292017-05-25 13:20:39 +0100394 */
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700395static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
Chris Morinc2cba7a2022-02-01 17:06:50 -0800396 const std::string& file_prefix) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100397 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100398
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700399 if (dump_dir == nullptr) {
400 MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno));
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700401 return std::vector<DumpData>();
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700402 }
403
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700404 std::vector<DumpData> dump_data;
Narayan Kamathbd863722017-06-01 18:50:12 +0100405 struct dirent* entry = nullptr;
406 while ((entry = readdir(dump_dir.get()))) {
407 if (entry->d_type != DT_REG) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100408 continue;
409 }
410
Narayan Kamathbd863722017-06-01 18:50:12 +0100411 const std::string base_name(entry->d_name);
412 if (base_name.find(file_prefix) != 0) {
413 continue;
414 }
415
416 const std::string abs_path = dir_path + base_name;
417 android::base::unique_fd fd(
418 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
419 if (fd == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700420 MYLOGW("Unable to open dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamathbd863722017-06-01 18:50:12 +0100421 break;
422 }
423
424 struct stat st = {};
425 if (fstat(fd, &st) == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700426 MYLOGW("Unable to stat dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamath8f788292017-05-25 13:20:39 +0100427 continue;
428 }
429
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700430 dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700431 }
Rhed Jao01dc0c62020-06-03 17:13:30 +0800432 if (!dump_data.empty()) {
433 std::sort(dump_data.begin(), dump_data.end(),
434 [](const auto& a, const auto& b) { return a.mtime > b.mtime; });
435 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100436
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700437 return dump_data;
Narayan Kamath8f788292017-05-25 13:20:39 +0100438}
439
Narayan Kamathbd863722017-06-01 18:50:12 +0100440static bool AddDumps(const std::vector<DumpData>::const_iterator start,
441 const std::vector<DumpData>::const_iterator end,
442 const char* type_name, const bool add_to_zip) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100443 bool dumped = false;
Narayan Kamathbd863722017-06-01 18:50:12 +0100444 for (auto it = start; it != end; ++it) {
445 const std::string& name = it->name;
446 const int fd = it->fd;
Narayan Kamath8f788292017-05-25 13:20:39 +0100447 dumped = true;
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100448
449 // Seek to the beginning of the file before dumping any data. A given
450 // DumpData entry might be dumped multiple times in the report.
451 //
452 // For example, the most recent ANR entry is dumped to the body of the
453 // main entry and it also shows up as a separate entry in the bugreport
454 // ZIP file.
455 if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) {
456 MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(),
457 strerror(errno));
458 }
459
Chris Morinc2cba7a2022-02-01 17:06:50 -0800460 if (add_to_zip) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800461 if (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd, /* timeout = */ 0ms) != OK) {
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100462 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100463 }
464 } else {
465 dump_file_from_fd(type_name, name.c_str(), fd);
466 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100467 }
468
469 return dumped;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700470}
471
Felipe Leme635ca312016-01-05 14:23:02 -0800472// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700473void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800474 char path[PATH_MAX];
475
476 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
477 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700478 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800479 char linkname[PATH_MAX];
480 ssize_t r = readlink(path, linkname, PATH_MAX);
481 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800482 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800483 return;
484 }
485 linkname[r] = '\0';
486
487 if (mount_points.find(linkname) == mount_points.end()) {
488 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700489 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700490 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
Felipe Leme635ca312016-01-05 14:23:02 -0800491 mount_points.insert(linkname);
492 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800493 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800494 }
495 }
496}
497
498void add_mountinfo() {
Felipe Leme678727a2016-09-21 17:22:11 -0700499 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800500 mount_points.clear();
Felipe Leme46b85da2016-11-21 17:40:45 -0800501 DurationReporter duration_reporter(title, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700502 for_each_pid(do_mountinfo, nullptr);
503 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800504}
505
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700506static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
507{
508 DIR *d;
509 struct dirent *de;
510 char path[PATH_MAX];
511
512 d = opendir(driverpath);
Yi Kong19d5c002018-07-20 13:39:55 -0700513 if (d == nullptr) {
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700514 return;
515 }
516
517 while ((de = readdir(d))) {
518 if (de->d_type != DT_LNK) {
519 continue;
520 }
521 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700522 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700523 }
524
525 closedir(d);
526}
527
Mark Salyzyn326842f2015-04-30 09:49:41 -0700528static bool skip_not_stat(const char *path) {
529 static const char stat[] = "/stat";
530 size_t len = strlen(path);
531 if (path[len - 1] == '/') { /* Directory? */
532 return false;
533 }
534 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
535}
536
Jeff Sharkey9df29d52023-02-06 14:26:30 -0700537static bool skip_wtf_strictmode(const char *path) {
538 if (strstr(path, "_wtf")) {
539 return true;
540 } else if (strstr(path, "_strictmode")) {
541 return true;
542 }
543 return false;
544}
545
Felipe Leme4c2d6632016-09-28 14:32:00 -0700546static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800547 return false;
548}
549
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700550unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700551
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800552//
553// stat offsets
554// Name units description
555// ---- ----- -----------
556// read I/Os requests number of read I/Os processed
557#define __STAT_READ_IOS 0
558// read merges requests number of read I/Os merged with in-queue I/O
559#define __STAT_READ_MERGES 1
560// read sectors sectors number of sectors read
561#define __STAT_READ_SECTORS 2
562// read ticks milliseconds total wait time for read requests
563#define __STAT_READ_TICKS 3
564// write I/Os requests number of write I/Os processed
565#define __STAT_WRITE_IOS 4
566// write merges requests number of write I/Os merged with in-queue I/O
567#define __STAT_WRITE_MERGES 5
568// write sectors sectors number of sectors written
569#define __STAT_WRITE_SECTORS 6
570// write ticks milliseconds total wait time for write requests
571#define __STAT_WRITE_TICKS 7
572// in_flight requests number of I/Os currently in flight
573#define __STAT_IN_FLIGHT 8
574// io_ticks milliseconds total time this block device has been active
575#define __STAT_IO_TICKS 9
576// time_in_queue milliseconds total wait time for all requests
577#define __STAT_IN_QUEUE 10
578#define __STAT_NUMBER_FIELD 11
579//
580// read I/Os, write I/Os
581// =====================
582//
583// These values increment when an I/O request completes.
584//
585// read merges, write merges
586// =========================
587//
588// These values increment when an I/O request is merged with an
589// already-queued I/O request.
590//
591// read sectors, write sectors
592// ===========================
593//
594// These values count the number of sectors read from or written to this
595// block device. The "sectors" in question are the standard UNIX 512-byte
596// sectors, not any device- or filesystem-specific block size. The
597// counters are incremented when the I/O completes.
598#define SECTOR_SIZE 512
599//
600// read ticks, write ticks
601// =======================
602//
603// These values count the number of milliseconds that I/O requests have
604// waited on this block device. If there are multiple I/O requests waiting,
605// these values will increase at a rate greater than 1000/second; for
606// example, if 60 read requests wait for an average of 30 ms, the read_ticks
607// field will increase by 60*30 = 1800.
608//
609// in_flight
610// =========
611//
612// This value counts the number of I/O requests that have been issued to
613// the device driver but have not yet completed. It does not include I/O
614// requests that are in the queue but not yet issued to the device driver.
615//
616// io_ticks
617// ========
618//
619// This value counts the number of milliseconds during which the device has
620// had I/O requests queued.
621//
622// time_in_queue
623// =============
624//
625// This value counts the number of milliseconds that I/O requests have waited
626// on this block device. If there are multiple I/O requests waiting, this
627// value will increase as the product of the number of milliseconds times the
628// number of requests waiting (see "read ticks" above for an example).
629#define S_TO_MS 1000
630//
631
Mark Salyzyn326842f2015-04-30 09:49:41 -0700632static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800633 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700634 bool z;
Yi Kong19d5c002018-07-20 13:39:55 -0700635 char *cp, *buffer = nullptr;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700636 size_t i = 0;
Josh Gao7c4258c2018-06-25 13:40:08 -0700637 FILE *fp = fdopen(dup(fd), "rb");
Mark Salyzyn326842f2015-04-30 09:49:41 -0700638 getline(&buffer, &i, fp);
639 fclose(fp);
640 if (!buffer) {
641 return -errno;
642 }
643 i = strlen(buffer);
644 while ((i > 0) && (buffer[i - 1] == '\n')) {
645 buffer[--i] = '\0';
646 }
647 if (!*buffer) {
648 free(buffer);
649 return 0;
650 }
651 z = true;
652 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800653 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700654 if (fields[i] != 0) {
655 z = false;
656 }
657 }
658 if (z) { /* never accessed */
659 free(buffer);
660 return 0;
661 }
662
Wei Wang509bb5d2017-06-09 14:42:12 -0700663 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
664 path += sizeof(BLK_DEV_SYS_DIR) - 1;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700665 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700666
667 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
668 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
669 "W-wait", "in-fli", "activ", "T-wait", path, buffer);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700670 free(buffer);
671
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800672 if (fields[__STAT_IO_TICKS]) {
673 unsigned long read_perf = 0;
674 unsigned long read_ios = 0;
675 if (fields[__STAT_READ_TICKS]) {
676 unsigned long long divisor = fields[__STAT_READ_TICKS]
677 * fields[__STAT_IO_TICKS];
678 read_perf = ((unsigned long long)SECTOR_SIZE
679 * fields[__STAT_READ_SECTORS]
680 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
681 / divisor;
682 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
683 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
684 / divisor;
685 }
686
687 unsigned long write_perf = 0;
688 unsigned long write_ios = 0;
689 if (fields[__STAT_WRITE_TICKS]) {
690 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
691 * fields[__STAT_IO_TICKS];
692 write_perf = ((unsigned long long)SECTOR_SIZE
693 * fields[__STAT_WRITE_SECTORS]
694 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
695 / divisor;
696 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
697 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
698 / divisor;
699 }
700
701 unsigned queue = (fields[__STAT_IN_QUEUE]
702 + (fields[__STAT_IO_TICKS] >> 1))
703 / fields[__STAT_IO_TICKS];
704
705 if (!write_perf && !write_ios) {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700706 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 -0800707 } else {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700708 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 -0800709 read_ios, write_perf, write_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800710 }
711
712 /* bugreport timeout factor adjustment */
713 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
714 worst_write_perf = write_perf;
715 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700716 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700717 return 0;
718}
719
Yao Chenbe3bbc12018-01-17 16:31:10 -0800720static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
721
Tom Cherryf4472f32020-08-05 09:31:17 -0700722// Returns the actual readable size of the given buffer or -1 on error.
723static long logcat_buffer_readable_size(const std::string& buffer) {
724 std::unique_ptr<logger_list, decltype(&android_logger_list_free)> logger_list{
725 android_logger_list_alloc(0, 0, 0), &android_logger_list_free};
726 auto logger = android_logger_open(logger_list.get(), android_name_to_log_id(buffer.c_str()));
727
728 return android_logger_get_log_readable_size(logger);
729}
730
731// Returns timeout in ms to read a list of buffers.
Yao Chenbe3bbc12018-01-17 16:31:10 -0800732static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
733 unsigned long timeout_ms = 0;
734 for (const auto& buffer : buffers) {
Tom Cherryf4472f32020-08-05 09:31:17 -0700735 long readable_size = logcat_buffer_readable_size(buffer);
736 if (readable_size > 0) {
737 // Engineering margin is ten-fold our guess.
738 timeout_ms += 10 * (readable_size + worst_write_perf) / worst_write_perf;
739 }
Yao Chenbe3bbc12018-01-17 16:31:10 -0800740 }
741 return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700742}
743
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800744// Opens a socket and returns its file descriptor.
745static int open_socket(const char* service);
746
Nandana Duttd2f5f082019-01-18 17:13:52 +0000747Dumpstate::ConsentCallback::ConsentCallback() : result_(UNAVAILABLE), start_time_(Nanotime()) {
748}
749
750android::binder::Status Dumpstate::ConsentCallback::onReportApproved() {
751 std::lock_guard<std::mutex> lock(lock_);
752 result_ = APPROVED;
753 MYLOGD("User approved consent to share bugreport\n");
Paul Chang0d2aad72020-02-13 20:04:03 +0800754
755 // Maybe copy screenshot so calling app can display the screenshot to the user as soon as
756 // consent is granted.
757 if (ds.options_->is_screenshot_copied) {
758 return android::binder::Status::ok();
759 }
760
761 if (!ds.options_->do_screenshot || ds.options_->screenshot_fd.get() == -1 ||
762 !ds.do_early_screenshot_) {
763 return android::binder::Status::ok();
764 }
765
766 bool copy_succeeded = android::os::CopyFileToFd(ds.screenshot_path_,
767 ds.options_->screenshot_fd.get());
768 ds.options_->is_screenshot_copied = copy_succeeded;
769 if (copy_succeeded) {
770 android::os::UnlinkAndLogOnError(ds.screenshot_path_);
771 }
Nandana Duttd2f5f082019-01-18 17:13:52 +0000772 return android::binder::Status::ok();
773}
774
775android::binder::Status Dumpstate::ConsentCallback::onReportDenied() {
776 std::lock_guard<std::mutex> lock(lock_);
777 result_ = DENIED;
778 MYLOGW("User denied consent to share bugreport\n");
779 return android::binder::Status::ok();
780}
781
782UserConsentResult Dumpstate::ConsentCallback::getResult() {
783 std::lock_guard<std::mutex> lock(lock_);
784 return result_;
785}
786
787uint64_t Dumpstate::ConsentCallback::getElapsedTimeMs() const {
Hunter Knepshieldf0a39052020-01-03 14:53:04 -0800788 return (Nanotime() - start_time_) / NANOS_PER_MILLI;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000789}
790
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700791void Dumpstate::PrintHeader() const {
MÃ¥rten Kongstad60195a72022-09-20 14:14:20 +0200792 std::string build, fingerprint, radio, bootloader, network, sdkversion;
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700793 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700794
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700795 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
796 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700797 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
798 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
799 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
MÃ¥rten Kongstad60195a72022-09-20 14:14:20 +0200800 sdkversion = android::base::GetProperty("ro.build.version.sdk", "(unknown)");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700801 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
Colin Crossf45fa6b2012-03-26 12:38:26 -0700802
Felipe Lemed8b94e52016-12-08 10:21:44 -0800803 printf("========================================================\n");
804 printf("== dumpstate: %s\n", date);
805 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700806
Felipe Lemed8b94e52016-12-08 10:21:44 -0800807 printf("\n");
808 printf("Build: %s\n", build.c_str());
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700809 // NOTE: fingerprint entry format is important for other tools.
Felipe Lemed8b94e52016-12-08 10:21:44 -0800810 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
811 printf("Bootloader: %s\n", bootloader.c_str());
812 printf("Radio: %s\n", radio.c_str());
813 printf("Network: %s\n", network.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100814 int64_t module_metadata_version = android::os::GetModuleMetadataVersion();
815 if (module_metadata_version != 0) {
816 printf("Module Metadata version: %" PRId64 "\n", module_metadata_version);
817 }
MÃ¥rten Kongstad60195a72022-09-20 14:14:20 +0200818 printf("Android SDK version: %s\n", sdkversion.c_str());
819 printf("SDK extensions: ");
820 RunCommandToFd(STDOUT_FILENO, "", {SDK_EXT_INFO, "--header"},
821 CommandOptions::WithTimeout(1).Always().DropRoot().Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700822
Felipe Lemed8b94e52016-12-08 10:21:44 -0800823 printf("Kernel: ");
Felipe Lemef0292972016-11-22 13:57:05 -0800824 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
Felipe Lemed8b94e52016-12-08 10:21:44 -0800825 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
Devin Moore09fde8d2023-03-21 16:28:22 +0000826 printf("Bootconfig: ");
827 DumpFileToFd(STDOUT_FILENO, "", "/proc/bootconfig");
Felipe Leme7709f8a2017-12-05 09:30:09 -0800828 printf("Uptime: ");
829 RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"},
830 CommandOptions::WithTimeout(1).Always().Build());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800831 printf("Bugreport format version: %s\n", version_.c_str());
Kevin Jeonfa64e642023-07-27 11:36:41 -0400832 printf(
833 "Dumpstate info: id=%d pid=%d dry_run=%d parallel_run=%d strict_run=%d args=%s "
834 "bugreport_mode=%s\n",
835 id_, pid_, PropertiesHelper::IsDryRun(), PropertiesHelper::IsParallelRun(),
836 PropertiesHelper::IsStrictRun(), options_->args.c_str(),
837 options_->bugreport_mode_string.c_str());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800838 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800839}
840
Felipe Leme24b66ee2016-06-16 10:55:26 -0700841// List of file extensions that can cause a zip file attachment to be rejected by some email
842// service providers.
843static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
844 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
845 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
846 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
847};
848
Vishnu Naire97d6122018-01-18 13:58:56 -0800849status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd,
850 std::chrono::milliseconds timeout = 0ms) {
Felipe Leme24b66ee2016-06-16 10:55:26 -0700851 std::string valid_name = entry_name;
852
853 // Rename extension if necessary.
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -0700854 size_t idx = entry_name.rfind('.');
Felipe Leme24b66ee2016-06-16 10:55:26 -0700855 if (idx != std::string::npos) {
856 std::string extension = entry_name.substr(idx);
857 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
858 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
859 valid_name = entry_name + ".renamed";
860 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
861 }
862 }
863
Felipe Leme6fe9db62016-02-12 09:04:16 -0800864 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
865 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Kevin Jeon9bbe0ac2022-05-05 22:05:43 +0000866 size_t flags = ZipWriter::kCompress | ZipWriter::kDefaultCompression;
867 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), flags,
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700868 get_mtime(fd, ds.now_));
Felipe Leme1d486fe2016-10-14 18:06:47 -0700869 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700870 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700871 ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800872 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800873 }
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000874 bool finished_entry = false;
875 auto finish_entry = [this, &finished_entry] {
876 if (!finished_entry) {
877 // This should only be called when we're going to return an earlier error,
878 // which would've been logged. This may imply the file is already corrupt
879 // and any further logging from FinishEntry is more likely to mislead than
880 // not.
881 this->zip_writer_->FinishEntry();
882 }
883 };
884 auto scope_guard = android::base::make_scope_guard(finish_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -0800885 auto start = std::chrono::steady_clock::now();
886 auto end = start + timeout;
887 struct pollfd pfd = {fd, POLLIN};
Felipe Lemee82a27d2016-01-05 13:35:44 -0800888
Felipe Leme770410d2016-01-26 17:07:14 -0800889 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800890 while (1) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800891 if (timeout.count() > 0) {
892 // lambda to recalculate the timeout.
893 auto time_left_ms = [end]() {
894 auto now = std::chrono::steady_clock::now();
895 auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
896 return std::max(diff.count(), 0LL);
897 };
898
899 int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
900 if (rc < 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000901 MYLOGE("Error in poll while adding from fd to zip entry %s:%s\n",
902 entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800903 return -errno;
904 } else if (rc == 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000905 MYLOGE("Timed out adding from fd to zip entry %s:%s Timeout:%lldms\n",
Vishnu Naire97d6122018-01-18 13:58:56 -0800906 entry_name.c_str(), strerror(errno), timeout.count());
907 return TIMED_OUT;
908 }
909 }
910
Zach Riggle22200402016-08-18 01:01:24 -0400911 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800912 if (bytes_read == 0) {
913 break;
914 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800915 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800916 return -errno;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800917 }
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700918 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800919 if (err) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700920 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800921 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800922 }
923 }
924
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700925 err = zip_writer_->FinishEntry();
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000926 finished_entry = true;
Felipe Leme1d486fe2016-10-14 18:06:47 -0700927 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700928 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800929 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800930 }
931
Vishnu Naire97d6122018-01-18 13:58:56 -0800932 return OK;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800933}
934
Felipe Leme1d486fe2016-10-14 18:06:47 -0700935bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
936 android::base::unique_fd fd(
937 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700938 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800939 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800940 return false;
941 }
942
Vishnu Naire97d6122018-01-18 13:58:56 -0800943 return (AddZipEntryFromFd(entry_name, fd.get()) == OK);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800944}
945
946/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700947static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800948 return (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) == OK) ? 0 : 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800949}
950
Felipe Leme1d486fe2016-10-14 18:06:47 -0700951void Dumpstate::AddDir(const std::string& dir, bool recursive) {
Felipe Leme678727a2016-09-21 17:22:11 -0700952 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
Felipe Leme46b85da2016-11-21 17:40:45 -0800953 DurationReporter duration_reporter(dir, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700954 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800955}
956
Felipe Leme1d486fe2016-10-14 18:06:47 -0700957bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800958 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Kevin Jeon9bbe0ac2022-05-05 22:05:43 +0000959 size_t flags = ZipWriter::kCompress | ZipWriter::kDefaultCompression;
960 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), flags, ds.now_);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700961 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700962 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700963 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800964 return false;
965 }
966
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700967 err = zip_writer_->WriteBytes(content.c_str(), content.length());
Felipe Leme1d486fe2016-10-14 18:06:47 -0700968 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700969 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700970 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800971 return false;
972 }
973
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700974 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700975 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700976 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800977 return false;
978 }
979
980 return true;
981}
982
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800983static void DoKmsg() {
984 struct stat st;
985 if (!stat(PSTORE_LAST_KMSG, &st)) {
986 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
987 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
988 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
989 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
990 } else {
991 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
992 DumpFile("LAST KMSG", "/proc/last_kmsg");
993 }
994}
995
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800996static void DoKernelLogcat() {
Yao Chenbe3bbc12018-01-17 16:31:10 -0800997 unsigned long timeout_ms = logcat_timeout({"kernel"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800998 RunCommand(
999 "KERNEL LOG",
1000 {"logcat", "-b", "kernel", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1001 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1002}
1003
Nandana Duttdb379fa2019-10-09 16:54:41 +01001004static void DoSystemLogcat(time_t since) {
1005 char since_str[80];
1006 strftime(since_str, sizeof(since_str), "%Y-%m-%d %H:%M:%S.000", localtime(&since));
1007
1008 unsigned long timeout_ms = logcat_timeout({"main", "system", "crash"});
1009 RunCommand("SYSTEM LOG",
1010 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v", "-T",
1011 since_str},
1012 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1013}
1014
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001015static void DoRadioLogcat() {
1016 unsigned long timeout_ms = logcat_timeout({"radio"});
1017 RunCommand(
1018 "RADIO LOG",
1019 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1020 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
1021}
1022
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001023static void DoLogcat() {
Vishnu Nair6921f802017-11-22 09:17:23 -08001024 unsigned long timeout_ms;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001025 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
1026 // calculate timeout
Yao Chenbe3bbc12018-01-17 16:31:10 -08001027 timeout_ms = logcat_timeout({"main", "system", "crash"});
Tony Makae737652017-03-30 17:47:09 +01001028 RunCommand("SYSTEM LOG",
Vishnu Nair6921f802017-11-22 09:17:23 -08001029 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1030 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -08001031 timeout_ms = logcat_timeout({"events"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001032 RunCommand(
1033 "EVENT LOG",
1034 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001035 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Yao Chenbe3bbc12018-01-17 16:31:10 -08001036 timeout_ms = logcat_timeout({"stats"});
1037 RunCommand(
1038 "STATS LOG",
1039 {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001040 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001041 DoRadioLogcat();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001042
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001043 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001044 RunCommand("LAST LOGCAT", {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable",
1045 "-v", "uid", "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001046}
1047
Mike Ma5c267872019-08-21 11:31:34 -07001048static void DumpIncidentReport() {
Mike Ma5c267872019-08-21 11:31:34 -07001049 const std::string path = ds.bugreport_internal_dir_ + "/tmp_incident_report";
1050 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1051 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1052 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1053 if (fd < 0) {
1054 MYLOGE("Could not open %s to dump incident report.\n", path.c_str());
1055 return;
1056 }
Kevin Jeonfa64e642023-07-27 11:36:41 -04001057 RunCommandToFd(fd, "", {"incident", "-u"},
1058 CommandOptions::WithTimeout(PropertiesHelper::IsStrictRun() ? 20 : 120).Build());
Mike Ma5c267872019-08-21 11:31:34 -07001059 bool empty = 0 == lseek(fd, 0, SEEK_END);
1060 if (!empty) {
1061 // Use a different name from "incident.proto"
1062 // /proto/incident.proto is reserved for incident service dump
1063 // i.e. metadata for debugging.
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001064 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "incident_report" + kProtoExt,
1065 path);
1066 } else {
1067 unlink(path.c_str());
Mike Ma5c267872019-08-21 11:31:34 -07001068 }
Mike Ma5c267872019-08-21 11:31:34 -07001069}
1070
Aaron Huang24d215d2022-04-27 18:51:16 +08001071static void DumpNetstatsProto() {
1072 const std::string path = ds.bugreport_internal_dir_ + "/tmp_netstats_proto";
1073 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1074 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1075 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1076 if (fd < 0) {
1077 MYLOGE("Could not open %s to dump netstats proto.\n", path.c_str());
1078 return;
1079 }
1080 RunCommandToFd(fd, "", {"dumpsys", "netstats", "--proto"},
Kevin Jeon2fb3dd62022-09-28 18:48:55 +00001081 CommandOptions::WithTimeout(5).Build());
Aaron Huang24d215d2022-04-27 18:51:16 +08001082 bool empty = 0 == lseek(fd, 0, SEEK_END);
1083 if (!empty) {
1084 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "netstats" + kProtoExt,
1085 path);
1086 } else {
1087 unlink(path.c_str());
1088 }
1089}
1090
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001091static void MaybeAddSystemTraceToZip() {
1092 // This function copies into the .zip the system trace that was snapshotted
Kean Mariottica20f2d2023-12-15 09:34:25 +00001093 // by the early call to MaybeSnapshotSystemTraceAsync(), if any background
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001094 // tracing was happening.
Kean Mariotti853b73a2023-07-27 12:40:30 +00001095 bool system_trace_exists = access(SYSTEM_TRACE_SNAPSHOT, F_OK) == 0;
1096 if (!system_trace_exists) {
Kean Mariottica20f2d2023-12-15 09:34:25 +00001097 // No background trace was happening at the time MaybeSnapshotSystemTraceAsync() was invoked
Kean Mariotti853b73a2023-07-27 12:40:30 +00001098 if (!PropertiesHelper::IsUserBuild()) {
1099 MYLOGI(
1100 "No system traces found. Check for previously uploaded traces by looking for "
1101 "go/trace-uuid in logcat")
1102 }
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001103 return;
1104 }
1105 ds.AddZipEntry(
1106 ZIP_ROOT_DIR + SYSTEM_TRACE_SNAPSHOT,
1107 SYSTEM_TRACE_SNAPSHOT);
1108 android::os::UnlinkAndLogOnError(SYSTEM_TRACE_SNAPSHOT);
1109}
1110
Sunny Goyal35949782019-11-19 15:54:36 -08001111static void DumpVisibleWindowViews() {
Sunny Goyal35949782019-11-19 15:54:36 -08001112 DurationReporter duration_reporter("VISIBLE WINDOW VIEWS");
1113 const std::string path = ds.bugreport_internal_dir_ + "/tmp_visible_window_views";
1114 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1115 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1116 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1117 if (fd < 0) {
1118 MYLOGE("Could not open %s to dump visible views.\n", path.c_str());
1119 return;
1120 }
1121 RunCommandToFd(fd, "", {"cmd", "window", "dump-visible-window-views"},
Kevin Jeon774abde2022-09-28 18:20:43 +00001122 CommandOptions::WithTimeout(10).Build());
Sunny Goyal35949782019-11-19 15:54:36 -08001123 bool empty = 0 == lseek(fd, 0, SEEK_END);
1124 if (!empty) {
1125 ds.AddZipEntry("visible_windows.zip", path);
1126 } else {
1127 MYLOGW("Failed to dump visible windows\n");
1128 }
1129 unlink(path.c_str());
1130}
1131
Jayachandran Ca94c7172017-06-10 15:08:12 -07001132static void DumpIpTablesAsRoot() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001133 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
1134 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +09001135 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001136 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +09001137 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
1138 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
1139 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
1140 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001141}
1142
Woody Lin20767a92022-11-29 15:50:24 +08001143static void DumpShutdownCheckpoints() {
1144 const bool shutdown_checkpoints_dumped = AddDumps(
1145 ds.shutdown_checkpoints_.begin(), ds.shutdown_checkpoints_.end(),
1146 "SHUTDOWN CHECKPOINTS", false /* add_to_zip */);
1147 if (!shutdown_checkpoints_dumped) {
1148 printf("*** NO SHUTDOWN CHECKPOINTS to dump in %s\n\n",
1149 SHUTDOWN_CHECKPOINTS_DIR.c_str());
1150 }
1151}
1152
David Andersond9ba4752018-12-11 18:26:59 -08001153static void DumpDynamicPartitionInfo() {
1154 if (!::android::base::GetBoolProperty("ro.boot.dynamic_partitions", false)) {
1155 return;
1156 }
1157
1158 RunCommand("LPDUMP", {"lpdump", "--all"});
David Anderson6650ade2019-10-02 15:18:59 -07001159 RunCommand("DEVICE-MAPPER", {"gsid", "dump-device-mapper"});
David Andersond9ba4752018-12-11 18:26:59 -08001160}
1161
Chris Morin5a50d482022-02-01 17:41:18 -08001162static void AddAnrTraceDir(const std::string& anr_traces_dir) {
Narayan Kamath8f788292017-05-25 13:20:39 +01001163 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
1164 anr_traces_dir.c_str());
1165
1166 // If we're here, dump_traces_path will always be a temporary file
1167 // (created with mkostemp or similar) that contains dumps taken earlier
1168 // on in the process.
1169 if (dump_traces_path != nullptr) {
Chris Morin5a50d482022-02-01 17:41:18 -08001170 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
1171 dump_traces_path);
1172 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
Narayan Kamath8f788292017-05-25 13:20:39 +01001173
1174 const int ret = unlink(dump_traces_path);
1175 if (ret == -1) {
1176 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
1177 strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -07001178 }
1179 }
1180
Narayan Kamathbd863722017-06-01 18:50:12 +01001181 // Add a specific message for the first ANR Dump.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001182 if (ds.anr_data_.size() > 0) {
Chris Morin5a50d482022-02-01 17:41:18 -08001183 // The "last" ANR will always be present in the body of the main entry.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001184 AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1,
Chris Morin5a50d482022-02-01 17:41:18 -08001185 "VM TRACES AT LAST ANR", false /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001186
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001187 // Historical ANRs are always included as separate entries in the bugreport zip file.
Chris Morin5a50d482022-02-01 17:41:18 -08001188 AddDumps(ds.anr_data_.begin(), ds.anr_data_.end(),
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001189 "HISTORICAL ANR", true /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001190 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +01001191 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
1192 }
Andy Hungd62f7e62024-01-11 15:47:52 -08001193
1194 // Add Java anr traces (such as generated by the Finalizer Watchdog).
1195 AddDumps(ds.anr_trace_data_.begin(), ds.anr_trace_data_.end(), "JAVA ANR TRACES",
1196 true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001197}
1198
1199static void AddAnrTraceFiles() {
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001200 std::string anr_traces_dir = "/data/anr";
Narayan Kamath8f788292017-05-25 13:20:39 +01001201
Chris Morin5a50d482022-02-01 17:41:18 -08001202 AddAnrTraceDir(anr_traces_dir);
Narayan Kamath8f788292017-05-25 13:20:39 +01001203
Makoto Onuki83ec63f2019-01-31 17:08:59 -08001204 RunCommand("ANR FILES", {"ls", "-lt", ANR_DIR});
1205
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001206 // Slow traces for slow operations.
Felipe Lemee184f662016-10-27 10:04:47 -07001207 struct stat st;
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001208 int i = 0;
1209 while (true) {
1210 const std::string slow_trace_path =
1211 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
1212 if (stat(slow_trace_path.c_str(), &st)) {
1213 // No traces file at this index, done with the files.
1214 break;
Felipe Lemee184f662016-10-27 10:04:47 -07001215 }
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001216 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
1217 i++;
Felipe Lemee184f662016-10-27 10:04:47 -07001218 }
1219}
1220
Wei Wang509bb5d2017-06-09 14:42:12 -07001221static void DumpBlockStatFiles() {
1222 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -07001223
Wei Wang1dc1ef52017-06-12 11:28:37 -07001224 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
1225
1226 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001227 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1228 return;
1229 }
1230
1231 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -07001232 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001233 if ((d->d_name[0] == '.')
1234 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1235 || (d->d_name[1] == '\0'))) {
1236 continue;
1237 }
1238 const std::string new_path =
1239 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1240 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1241 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1242 printf("\n");
1243 }
Wei Wang1dc1ef52017-06-12 11:28:37 -07001244 return;
Wei Wang509bb5d2017-06-09 14:42:12 -07001245}
Jayachandran Ca94c7172017-06-10 15:08:12 -07001246
1247static void DumpPacketStats() {
1248 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
Jayachandran Ca94c7172017-06-10 15:08:12 -07001249}
1250
1251static void DumpIpAddrAndRules() {
1252 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
Ray Chencbf278a2023-11-20 07:49:45 +00001253 RunCommand("NETWORK INTERFACES", {"ip", "-s", "link"});
Jayachandran Ca94c7172017-06-10 15:08:12 -07001254 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1255 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1256 RunCommand("IP RULES", {"ip", "rule", "show"});
1257 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1258}
1259
Nandana Dutt5c390032019-03-12 10:52:56 +00001260static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, int priority,
1261 std::chrono::milliseconds timeout,
1262 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001263 auto start = std::chrono::steady_clock::now();
Vishnu Naire97d6122018-01-18 13:58:56 -08001264 sp<android::IServiceManager> sm = defaultServiceManager();
1265 Dumpsys dumpsys(sm.get());
Vishnu Naire97d6122018-01-18 13:58:56 -08001266 Vector<String16> args;
1267 Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
Vishnu Naire97d6122018-01-18 13:58:56 -08001268 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1269 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001270 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001271 std::string path(title);
1272 path.append(" - ").append(String8(service).c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -08001273 size_t bytes_written = 0;
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001274 if (PropertiesHelper::IsDryRun()) {
1275 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1276 dumpsys.writeDumpFooter(STDOUT_FILENO, service, std::chrono::milliseconds(1));
1277 } else {
Devin Mooref492c1a2023-03-15 19:19:03 +00001278 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP | Dumpsys::TYPE_PID |
1279 Dumpsys::TYPE_CLIENTS | Dumpsys::TYPE_THREAD,
Devin Mooreae68df22023-02-24 20:59:51 +00001280 service, args);
1281 if (status == OK) {
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001282 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1283 std::chrono::duration<double> elapsed_seconds;
1284 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH &&
1285 service == String16("meminfo")) {
1286 // Use a longer timeout for meminfo, since 30s is not always enough.
1287 status = dumpsys.writeDump(STDOUT_FILENO, service, 60s,
1288 /* as_proto = */ false, elapsed_seconds,
1289 bytes_written);
1290 } else {
1291 status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
1292 /* as_proto = */ false, elapsed_seconds,
1293 bytes_written);
1294 }
1295 dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
1296 bool dump_complete = (status == OK);
1297 dumpsys.stopDumpThread(dump_complete);
Devin Moorecdfa4602023-03-16 20:49:39 +00001298 } else {
1299 MYLOGE("Failed to start dump thread for service: %s, status: %d",
1300 String8(service).c_str(), status);
Gavin Corkeryfac7e2b2021-07-08 22:39:02 +01001301 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001302 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001303
1304 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1305 std::chrono::steady_clock::now() - start);
1306 if (elapsed_duration > timeout) {
1307 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1308 elapsed_duration.count());
1309 break;
1310 }
1311 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001312 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001313}
1314
Vishnu Nair64afc022018-02-01 15:29:34 -08001315static void RunDumpsysText(const std::string& title, int priority,
1316 std::chrono::milliseconds timeout,
1317 std::chrono::milliseconds service_timeout) {
1318 DurationReporter duration_reporter(title);
1319 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1320 fsync(STDOUT_FILENO);
1321 RunDumpsysTextByPriority(title, priority, timeout, service_timeout);
1322}
1323
1324/* Dump all services registered with Normal or Default priority. */
Nandana Dutt5c390032019-03-12 10:52:56 +00001325static Dumpstate::RunStatus RunDumpsysTextNormalPriority(const std::string& title,
1326 std::chrono::milliseconds timeout,
1327 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001328 DurationReporter duration_reporter(title);
1329 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1330 fsync(STDOUT_FILENO);
1331 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout,
1332 service_timeout);
Nandana Dutt5c390032019-03-12 10:52:56 +00001333
1334 RETURN_IF_USER_DENIED_CONSENT();
1335
1336 return RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1337 service_timeout);
Vishnu Nair64afc022018-02-01 15:29:34 -08001338}
1339
Nandana Dutt5c390032019-03-12 10:52:56 +00001340static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priority,
1341 std::chrono::milliseconds timeout,
1342 std::chrono::milliseconds service_timeout) {
Vishnu Naire97d6122018-01-18 13:58:56 -08001343 sp<android::IServiceManager> sm = defaultServiceManager();
1344 Dumpsys dumpsys(sm.get());
1345 Vector<String16> args;
1346 Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
1347 DurationReporter duration_reporter(title);
1348
1349 auto start = std::chrono::steady_clock::now();
1350 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
1351 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001352 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001353 std::string path(kProtoPath);
1354 path.append(String8(service).c_str());
1355 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
1356 path.append("_CRITICAL");
1357 } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
1358 path.append("_HIGH");
1359 }
1360 path.append(kProtoExt);
Steven Morelandcbd69fc2021-07-20 20:45:43 +00001361 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP, service, args);
Vishnu Naire97d6122018-01-18 13:58:56 -08001362 if (status == OK) {
1363 status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
1364 bool dumpTerminated = (status == OK);
1365 dumpsys.stopDumpThread(dumpTerminated);
1366 }
1367 ZipWriter::FileEntry file_entry;
1368 ds.zip_writer_->GetLastEntry(&file_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -08001369
1370 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1371 std::chrono::steady_clock::now() - start);
1372 if (elapsed_duration > timeout) {
1373 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1374 elapsed_duration.count());
1375 break;
1376 }
1377 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001378 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001379}
1380
Nandana Dutta7db6342018-11-21 14:53:34 +00001381// Runs dumpsys on services that must dump first and will take less than 100ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001382static Dumpstate::RunStatus RunDumpsysCritical() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001383 RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1384 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Nandana Dutt5c390032019-03-12 10:52:56 +00001385
1386 RETURN_IF_USER_DENIED_CONSENT();
1387
1388 return RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1389 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Vishnu Nair780b1282017-10-10 13:57:24 -07001390}
1391
1392// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001393static Dumpstate::RunStatus RunDumpsysHigh() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001394 // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
1395 // high priority. Reduce timeout once they are able to dump in a shorter time or
1396 // moved to a parallel task.
1397 RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1398 /* timeout= */ 90s, /* service_timeout= */ 30s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001399
1400 RETURN_IF_USER_DENIED_CONSENT();
1401
1402 return RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1403 /* timeout= */ 5s, /* service_timeout= */ 1s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001404}
1405
1406// Runs dumpsys on services that must dump but can take up to 10s to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001407static Dumpstate::RunStatus RunDumpsysNormal() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001408 RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001409
1410 RETURN_IF_USER_DENIED_CONSENT();
1411
1412 return RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1413 /* timeout= */ 90s, /* service_timeout= */ 10s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001414}
1415
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001416/*
1417 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1418 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1419 * if it's not running in the parallel task.
1420 */
1421static void DumpHals(int out_fd = STDOUT_FILENO) {
Yifan Hong30528a22020-08-07 18:24:06 -07001422 RunCommand("HARDWARE HALS", {"lshal", "--all", "--types=all"},
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001423 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build(),
1424 false, out_fd);
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001425
Steven Moreland44cd9482018-01-04 16:24:13 -08001426 using android::hidl::manager::V1_0::IServiceManager;
1427 using android::hardware::defaultServiceManager;
1428
1429 sp<IServiceManager> sm = defaultServiceManager();
1430 if (sm == nullptr) {
1431 MYLOGE("Could not retrieve hwservicemanager to dump hals.\n");
1432 return;
1433 }
1434
1435 auto ret = sm->list([&](const auto& interfaces) {
1436 for (const std::string& interface : interfaces) {
1437 std::string cleanName = interface;
Steven Morelandc6b1fc22023-07-26 23:53:58 +00001438 std::replace_if(
1439 cleanName.begin(), cleanName.end(),
1440 [](char c) {
1441 return !isalnum(c) && std::string("@-_.").find(c) == std::string::npos;
1442 },
1443 '_');
Nandana Dutt979388e2018-11-30 16:48:55 +00001444 const std::string path = ds.bugreport_internal_dir_ + "/lshal_debug_" + cleanName;
Steven Moreland44cd9482018-01-04 16:24:13 -08001445
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001446 bool empty = false;
Steven Moreland44cd9482018-01-04 16:24:13 -08001447 {
1448 auto fd = android::base::unique_fd(
1449 TEMP_FAILURE_RETRY(open(path.c_str(),
1450 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1451 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1452 if (fd < 0) {
1453 MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str());
1454 continue;
1455 }
1456 RunCommandToFd(fd,
1457 "",
Steven Morelandc81cd3c2018-01-18 14:36:26 -08001458 {"lshal", "debug", "-E", interface},
Steven Moreland44cd9482018-01-04 16:24:13 -08001459 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1460
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001461 empty = 0 == lseek(fd, 0, SEEK_END);
Steven Moreland44cd9482018-01-04 16:24:13 -08001462 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001463 if (!empty) {
1464 ds.EnqueueAddZipEntryAndCleanupIfNeeded("lshal-debug/" + cleanName + ".txt",
1465 path);
1466 } else {
1467 unlink(path.c_str());
1468 }
Steven Moreland44cd9482018-01-04 16:24:13 -08001469 }
1470 });
1471
1472 if (!ret.isOk()) {
1473 MYLOGE("Could not list hals from hwservicemanager.\n");
1474 }
1475}
1476
Devin Moore8df81bb2022-06-08 22:47:02 +00001477// Dump all of the files that make up the vendor interface.
1478// See the files listed in dumpFileList() for the latest list of files.
1479static void DumpVintf() {
Devin Moore16271d92022-09-22 18:28:48 +00001480
1481 const std::string sku = android::base::GetProperty("ro.boot.product.hardware.sku", "");
1482 const auto vintfFiles = android::vintf::details::dumpFileList(sku);
Devin Moore8df81bb2022-06-08 22:47:02 +00001483 for (const auto vintfFile : vintfFiles) {
1484 struct stat st;
1485 if (stat(vintfFile.c_str(), &st) == 0) {
1486 if (S_ISDIR(st.st_mode)) {
1487 ds.AddDir(vintfFile, true /* recursive */);
1488 } else {
1489 ds.EnqueueAddZipEntryAndCleanupIfNeeded(ZIP_ROOT_DIR + vintfFile,
1490 vintfFile);
1491 }
1492 }
1493 }
1494}
1495
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001496static void DumpExternalFragmentationInfo() {
1497 struct stat st;
1498 if (stat("/proc/buddyinfo", &st) != 0) {
1499 MYLOGE("Unable to dump external fragmentation info\n");
1500 return;
1501 }
1502
1503 printf("------ EXTERNAL FRAGMENTATION INFO ------\n");
1504 std::ifstream ifs("/proc/buddyinfo");
1505 auto unusable_index_regex = std::regex{"Node\\s+([0-9]+),\\s+zone\\s+(\\S+)\\s+(.*)"};
1506 for (std::string line; std::getline(ifs, line);) {
1507 std::smatch match_results;
1508 if (std::regex_match(line, match_results, unusable_index_regex)) {
1509 std::stringstream free_pages(std::string{match_results[3]});
1510 std::vector<int> free_pages_per_order(std::istream_iterator<int>{free_pages},
1511 std::istream_iterator<int>());
1512
1513 int total_free_pages = 0;
1514 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1515 total_free_pages += (free_pages_per_order[i] * std::pow(2, i));
1516 }
1517
1518 printf("Node %s, zone %8s", match_results[1].str().c_str(),
1519 match_results[2].str().c_str());
1520
1521 int usable_free_pages = total_free_pages;
1522 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1523 auto unusable_index = (total_free_pages - usable_free_pages) /
1524 static_cast<double>(total_free_pages);
1525 printf(" %5.3f", unusable_index);
1526 usable_free_pages -= (free_pages_per_order[i] * std::pow(2, i));
1527 }
1528
1529 printf("\n");
1530 }
1531 }
1532 printf("\n");
1533}
1534
mhasankd451a472020-05-26 18:02:39 -07001535static void DumpstateLimitedOnly() {
EdenSue8fe4522023-11-20 15:37:23 +08001536 // Trimmed-down version of dumpstate to only include a allowlisted
mhasankd451a472020-05-26 18:02:39 -07001537 // set of logs (system log, event log, and system server / system app
1538 // crashes, and networking logs). See b/136273873 and b/138459828
1539 // for context.
1540 DurationReporter duration_reporter("DUMPSTATE");
1541 unsigned long timeout_ms;
1542 // calculate timeout
1543 timeout_ms = logcat_timeout({"main", "system", "crash"});
1544 RunCommand("SYSTEM LOG",
1545 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1546 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1547 timeout_ms = logcat_timeout({"events"});
1548 RunCommand(
1549 "EVENT LOG",
1550 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1551 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1552
1553 printf("========================================================\n");
1554 printf("== Networking Service\n");
1555 printf("========================================================\n");
1556
1557 RunDumpsys("DUMPSYS NETWORK_SERVICE_LIMITED", {"wifi", "-a"},
1558 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hugo Benichiaa162682020-10-30 23:28:56 +09001559 RunDumpsys("DUMPSYS CONNECTIVITY REQUESTS", {"connectivity", "requests"},
1560 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
mhasankd451a472020-05-26 18:02:39 -07001561
1562 printf("========================================================\n");
1563 printf("== Dropbox crashes\n");
1564 printf("========================================================\n");
1565
1566 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1567 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1568
Bryan Yuefb85d92024-02-02 13:37:06 +00001569
1570 printf("========================================================\n");
1571 printf("== ANR Traces\n");
1572 printf("========================================================\n");
1573
Bryan Yucf038cf2024-05-08 09:25:25 +00001574 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX);
Bryan Yuefb85d92024-02-02 13:37:06 +00001575 AddAnrTraceFiles();
1576
mhasankd451a472020-05-26 18:02:39 -07001577 printf("========================================================\n");
1578 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1579 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1580 printf("========================================================\n");
1581 printf("== dumpstate: done (id %d)\n", ds.id_);
1582 printf("========================================================\n");
1583}
1584
Rhed Jaoe017f982020-07-21 17:58:41 +08001585/*
1586 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1587 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1588 * if it's not running in the parallel task.
1589 */
1590static void DumpCheckins(int out_fd = STDOUT_FILENO) {
1591 dprintf(out_fd, "========================================================\n");
1592 dprintf(out_fd, "== Checkins\n");
1593 dprintf(out_fd, "========================================================\n");
1594
1595 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"}, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001596 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"}, out_fd);
1597 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"}, out_fd);
1598 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"}, out_fd);
1599 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"}, out_fd);
1600}
1601
1602/*
1603 * Runs dumpsys on activity service to dump all application activities, services
1604 * and providers in the device.
1605 *
1606 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1607 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1608 * if it's not running in the parallel task.
1609 */
1610static void DumpAppInfos(int out_fd = STDOUT_FILENO) {
1611 dprintf(out_fd, "========================================================\n");
1612 dprintf(out_fd, "== Running Application Activities\n");
1613 dprintf(out_fd, "========================================================\n");
1614
1615 // The following dumpsys internally collects output from running apps, so it can take a long
1616 // time. So let's extend the timeout.
1617
1618 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1619
1620 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1621
1622 dprintf(out_fd, "========================================================\n");
1623 dprintf(out_fd, "== Running Application Services (platform)\n");
1624 dprintf(out_fd, "========================================================\n");
1625
1626 RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
1627 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1628
1629 dprintf(out_fd, "========================================================\n");
1630 dprintf(out_fd, "== Running Application Services (non-platform)\n");
1631 dprintf(out_fd, "========================================================\n");
1632
1633 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1634 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1635
1636 dprintf(out_fd, "========================================================\n");
1637 dprintf(out_fd, "== Running Application Providers (platform)\n");
1638 dprintf(out_fd, "========================================================\n");
1639
1640 RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
Rhed Jaob049f182021-01-11 21:08:43 +08001641 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001642
1643 dprintf(out_fd, "========================================================\n");
1644 dprintf(out_fd, "== Running Application Providers (non-platform)\n");
1645 dprintf(out_fd, "========================================================\n");
1646
1647 RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1648 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1649}
1650
Nandana Dutt5c390032019-03-12 10:52:56 +00001651// Dumps various things. Returns early with status USER_CONSENT_DENIED if user denies consent
1652// via the consent they are shown. Ignores other errors that occur while running various
1653// commands. The consent checking is currently done around long running tasks, which happen to
1654// be distributed fairly evenly throughout the function.
Kean Mariotti306633e2022-09-05 16:30:47 +00001655Dumpstate::RunStatus Dumpstate::dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001656 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001657
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001658 // Enqueue slow functions into the thread pool, if the parallel run is enabled.
Aaron Huang24d215d2022-04-27 18:51:16 +08001659 std::future<std::string> dump_hals, dump_incident_report, dump_board, dump_checkins,
Kean Mariottica20f2d2023-12-15 09:34:25 +00001660 dump_netstats_report;
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001661 if (ds.dump_pool_) {
1662 // Pool was shutdown in DumpstateDefaultAfterCritical method in order to
Kean Mariotti306633e2022-09-05 16:30:47 +00001663 // drop root user. Restarts it.
1664 ds.dump_pool_->start(/* thread_counts = */3);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001665
Chris Morinbc223142022-02-04 14:17:11 -08001666 dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
1667 dump_incident_report = ds.dump_pool_->enqueueTask(
1668 DUMP_INCIDENT_REPORT_TASK, &DumpIncidentReport);
Aaron Huang24d215d2022-04-27 18:51:16 +08001669 dump_netstats_report = ds.dump_pool_->enqueueTask(
1670 DUMP_NETSTATS_PROTO_TASK, &DumpNetstatsProto);
Chris Morinbc223142022-02-04 14:17:11 -08001671 dump_board = ds.dump_pool_->enqueueTaskWithFd(
1672 DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
1673 dump_checkins = ds.dump_pool_->enqueueTaskWithFd(DUMP_CHECKINS_TASK, &DumpCheckins, _1);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001674 }
1675
Nandana Dutt5c390032019-03-12 10:52:56 +00001676 // Dump various things. Note that anything that takes "long" (i.e. several seconds) should
1677 // check intermittently (if it's intrerruptable like a foreach on pids) and/or should be wrapped
1678 // in a consent check (via RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK).
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001679 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001680 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001681 DumpBlockStatFiles();
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001682 DumpFile("MEMORY INFO", "/proc/meminfo");
1683 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001684 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001685
Kevin Jeon947922b2022-09-21 00:29:18 +00001686 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "BUGREPORT_PROCDUMP", {"bugreport_procdump"},
1687 CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001688
Sunny Goyal35949782019-11-19 15:54:36 -08001689 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpVisibleWindowViews);
1690
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001691 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1692 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1693 DumpFile("SLAB INFO", "/proc/slabinfo");
1694 DumpFile("ZONEINFO", "/proc/zoneinfo");
1695 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1696 DumpFile("BUDDYINFO", "/proc/buddyinfo");
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001697 DumpExternalFragmentationInfo();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001698
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001699 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001700
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001701 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001702 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001703
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001704 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001705 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_hals));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001706 } else {
1707 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_HALS_TASK, DumpHals);
1708 }
Steven Moreland81b429e2017-01-31 19:50:46 -08001709
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001710 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001711 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001712 struct stat s;
1713 if (stat("/proc/modules", &s) != 0) {
1714 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1715 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001716 RunCommand("LSMOD", {"lsmod"});
Woody Linc198f252021-05-04 16:37:11 +08001717 RunCommand("MODULES INFO",
1718 {"sh", "-c", "cat /proc/modules | cut -d' ' -f1 | "
1719 " while read MOD ; do echo modinfo:$MOD ; modinfo $MOD ; "
1720 "done"}, CommandOptions::AS_ROOT);
Felipe Lemee4eca582016-06-10 17:48:08 -07001721 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001722
Tom Cherryb87dbfa2020-07-28 11:28:53 -07001723 if (android::base::GetBoolProperty("ro.logd.kernel", false)) {
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001724 DoKernelLogcat();
1725 } else {
1726 do_dmesg();
1727 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001728
Devin Moore8df81bb2022-06-08 22:47:02 +00001729 DumpVintf();
1730
Felipe Lemef0292972016-11-22 13:57:05 -08001731 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001732
Jeff Brown1dc94e32014-09-11 14:15:27 -07001733 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001734 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001735
Jack Yu5a6b2e22020-08-14 18:13:35 +08001736 /* Dump Nfc NCI logs */
1737 ds.AddDir("/data/misc/nfc/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001738
Paul Chang0d2aad72020-02-13 20:04:03 +08001739 if (ds.options_->do_screenshot && !ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001740 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001741 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001742 }
1743
Felipe Lemee184f662016-10-27 10:04:47 -07001744 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001745
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001746 MaybeAddSystemTraceToZip();
1747
Narayan Kamath8f788292017-05-25 13:20:39 +01001748 // NOTE: tombstones are always added as separate entries in the zip archive
1749 // and are not interspersed with the main report.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001750 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
Narayan Kamathbd863722017-06-01 18:50:12 +01001751 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001752 if (!tombstones_dumped) {
1753 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001754 }
1755
Jayachandran Ca94c7172017-06-10 15:08:12 -07001756 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001757
Lorenzo Colitti807f2dd2022-05-27 12:48:37 +09001758 RunDumpsys("EBPF MAP STATS", {"connectivity", "trafficcontroller"});
Chenbo Feng276a3b62018-08-07 11:44:49 -07001759
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001760 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001761
Woody Lin20767a92022-11-29 15:50:24 +08001762 DumpShutdownCheckpoints();
1763
Jayachandran Ca94c7172017-06-10 15:08:12 -07001764 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001765
1766 dump_route_tables();
1767
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001768 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1769 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1770 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001771
Nandana Dutt5c390032019-03-12 10:52:56 +00001772 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysHigh);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001773
Chiachang Wang668ede42021-05-17 17:14:20 +08001774 // The dump mechanism in connectivity is refactored due to modularization work. Connectivity can
1775 // only register with a default priority(NORMAL priority). Dumpstate has to call connectivity
1776 // dump with priority parameters to dump high priority information.
1777 RunDumpsys("SERVICE HIGH connectivity", {"connectivity", "--dump-priority", "HIGH"},
1778 CommandOptions::WithTimeout(10).Build());
1779
Elliott Hughes23ccc622017-02-28 10:14:22 -08001780 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001781
Joe Onoratod38bc3a2023-06-29 15:48:28 -07001782 DumpFile("SYSTEM BUILD-TIME RELEASE FLAGS", "/system/etc/build_flags.json");
1783 DumpFile("SYSTEM_EXT BUILD-TIME RELEASE FLAGS", "/system_ext/etc/build_flags.json");
1784 DumpFile("PRODUCT BUILD-TIME RELEASE FLAGS", "/product/etc/build_flags.json");
1785 DumpFile("VENDOR BUILD-TIME RELEASE FLAGS", "/vendor/etc/build_flags.json");
1786
MÃ¥rten Kongstad5ad813f2023-09-28 10:09:18 +02001787 RunCommand("ACONFIG FLAGS", {PRINT_FLAGS},
1788 CommandOptions::WithTimeout(10).Always().DropRoot().Build());
Ted Bauerf6d61b82024-09-13 19:57:19 +00001789 RunCommand("ACONFIG FLAGS DUMP", {AFLAGS, "list"},
1790 CommandOptions::WithTimeout(10).Always().AsRootIfAvailable().Build());
1791 RunCommand("WHICH ACONFIG FLAG STORAGE", {AFLAGS, "which-backing"},
1792 CommandOptions::WithTimeout(10).Always().AsRootIfAvailable().Build());
Joe Onoratod38bc3a2023-06-29 15:48:28 -07001793
Jin Qianf334d662017-10-10 14:41:37 -07001794 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001795
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001796 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001797
Colin Crossf45fa6b2012-03-26 12:38:26 -07001798 /* Binder state is expensive to look at as it uses a lot of memory. */
Hridya Valsaraju920ba712020-02-09 16:27:01 -08001799 std::string binder_logs_dir = access("/dev/binderfs/binder_logs", R_OK) ?
1800 "/sys/kernel/debug/binder" : "/dev/binderfs/binder_logs";
1801
1802 DumpFile("BINDER FAILED TRANSACTION LOG", binder_logs_dir + "/failed_transaction_log");
1803 DumpFile("BINDER TRANSACTION LOG", binder_logs_dir + "/transaction_log");
1804 DumpFile("BINDER TRANSACTIONS", binder_logs_dir + "/transactions");
1805 DumpFile("BINDER STATS", binder_logs_dir + "/stats");
1806 DumpFile("BINDER STATE", binder_logs_dir + "/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001807
Yifan Hongd90cc652020-02-08 16:52:02 -08001808 ds.AddDir(SNAPSHOTCTL_LOG_DIR, false);
1809
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001810 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001811 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_board));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001812 } else {
1813 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
1814 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001815
Steven Moreland7440ddb2016-12-15 16:13:39 -08001816 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001817 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1818 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001819 // su does not exist on user builds, so try running without it.
1820 // This way any implementations of vril-dump that do not require
1821 // root can run on user builds.
1822 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001823 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001824 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001825 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001826 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001827 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001828 }
1829
Felipe Lemed8b94e52016-12-08 10:21:44 -08001830 printf("========================================================\n");
1831 printf("== Android Framework Services\n");
1832 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001833
Nandana Dutt5c390032019-03-12 10:52:56 +00001834 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001835
Jack He91ff2fe2021-02-18 18:23:43 -08001836 /* Dump Bluetooth HCI logs after getting bluetooth_manager dumpsys */
1837 ds.AddDir("/data/misc/bluetooth/logs", true);
1838
Rhed Jaoe017f982020-07-21 17:58:41 +08001839 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001840 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_checkins));
Rhed Jaoe017f982020-07-21 17:58:41 +08001841 } else {
1842 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_CHECKINS_TASK, DumpCheckins);
1843 }
Dianne Hackborn02bea972013-06-26 18:59:09 -07001844
Rhed Jaoc5f7ec32020-12-22 22:11:08 +08001845 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpAppInfos);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001846
Adrian Roos8b397ab2017-04-04 16:35:44 -07001847 printf("========================================================\n");
1848 printf("== Dropbox crashes\n");
1849 printf("========================================================\n");
1850
1851 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1852 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1853
Felipe Lemed8b94e52016-12-08 10:21:44 -08001854 printf("========================================================\n");
1855 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1856 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1857 printf("========================================================\n");
1858 printf("== dumpstate: done (id %d)\n", ds.id_);
1859 printf("========================================================\n");
Bookatz38472142018-09-28 10:20:24 -07001860
1861 printf("========================================================\n");
1862 printf("== Obtaining statsd metadata\n");
1863 printf("========================================================\n");
1864 // This differs from the usual dumpsys stats, which is the stats report data.
1865 RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
Mike Ma5c267872019-08-21 11:31:34 -07001866
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +09001867 // Add linker configuration directory
1868 ds.AddDir(LINKERCONFIG_DIR, true);
1869
Li Li830179f2022-01-04 12:53:29 -08001870 /* Dump frozen cgroupfs */
1871 dump_frozen_cgroupfs();
Li Li2eedd412021-06-30 15:11:53 -07001872
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001873 if (ds.dump_pool_) {
Aaron Huang24d215d2022-04-27 18:51:16 +08001874 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_netstats_report));
1875 } else {
1876 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_NETSTATS_PROTO_TASK,
1877 DumpNetstatsProto);
1878 }
1879
1880 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001881 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_incident_report));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001882 } else {
1883 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_INCIDENT_REPORT_TASK,
1884 DumpIncidentReport);
1885 }
Mike Ma5c267872019-08-21 11:31:34 -07001886
Kean Mariotti306633e2022-09-05 16:30:47 +00001887 MaybeAddUiTracesToZip();
1888
Nandana Dutt5c390032019-03-12 10:52:56 +00001889 return Dumpstate::RunStatus::OK;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001890}
1891
Nandana Dutt5c390032019-03-12 10:52:56 +00001892/*
1893 * Dumps state for the default case; drops root after it's no longer necessary.
1894 *
1895 * Returns RunStatus::OK if everything went fine.
1896 * Returns RunStatus::ERROR if there was an error.
1897 * Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport
1898 * with the caller.
1899 */
Jichao Lie89d9c12019-11-21 19:02:51 -08001900Dumpstate::RunStatus Dumpstate::DumpstateDefaultAfterCritical() {
Nandana Duttdb379fa2019-10-09 16:54:41 +01001901 // Capture first logcat early on; useful to take a snapshot before dumpstate logs take over the
1902 // buffer.
1903 DoLogcat();
1904 // Capture timestamp after first logcat to use in next logcat
1905 time_t logcat_ts = time(nullptr);
1906
Nandana Dutt4be45d12018-09-26 15:04:23 +01001907 /* collect stack traces from Dalvik and native processes (needs root) */
Chris Morinbc223142022-02-04 14:17:11 -08001908 std::future<std::string> dump_traces;
Rhed Jao5377d792020-07-16 17:37:39 +08001909 if (dump_pool_) {
1910 RETURN_IF_USER_DENIED_CONSENT();
1911 // One thread is enough since we only need to enqueue DumpTraces here.
1912 dump_pool_->start(/* thread_counts = */1);
1913
1914 // DumpTraces takes long time, post it to the another thread in the
1915 // pool, if pool is available
Chris Morinbc223142022-02-04 14:17:11 -08001916 dump_traces = dump_pool_->enqueueTask(
1917 DUMP_TRACES_TASK, &Dumpstate::DumpTraces, &ds, &dump_traces_path);
Rhed Jao5377d792020-07-16 17:37:39 +08001918 } else {
1919 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_TRACES_TASK, ds.DumpTraces,
1920 &dump_traces_path);
1921 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001922
1923 /* Run some operations that require root. */
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001924 if (!PropertiesHelper::IsDryRun()) {
Chris Morinc2cba7a2022-02-01 17:06:50 -08001925 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX);
1926 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX);
Andy Hungd62f7e62024-01-11 15:47:52 -08001927 ds.anr_trace_data_ = GetDumpFds(ANR_DIR, ANR_TRACE_FILE_PREFIX);
Woody Lin20767a92022-11-29 15:50:24 +08001928 ds.shutdown_checkpoints_ = GetDumpFds(
1929 SHUTDOWN_CHECKPOINTS_DIR, SHUTDOWN_CHECKPOINTS_FILE_PREFIX);
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001930 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001931
1932 ds.AddDir(RECOVERY_DIR, true);
1933 ds.AddDir(RECOVERY_DATA_DIR, true);
1934 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
Kelvin Zhang6eaa0f92022-09-12 09:29:19 -07001935 ds.AddDir(UPDATE_ENGINE_PREF_DIR, true);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001936 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1937 if (!PropertiesHelper::IsUserBuild()) {
1938 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1939 ds.AddDir(PROFILE_DATA_DIR_REF, true);
Calin Juravlef84d3692020-04-28 15:31:12 -07001940 ds.AddZipEntry(ZIP_ROOT_DIR + PACKAGE_DEX_USE_LIST, PACKAGE_DEX_USE_LIST);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001941 }
Jerry Changa1df8a92020-01-02 16:03:39 +08001942 ds.AddDir(PREREBOOT_DATA_DIR, false);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001943 add_mountinfo();
Peter Collingbourne78aa2942023-02-15 14:50:31 -08001944 for (const char* path : {"/proc/cpuinfo", "/proc/meminfo"}) {
1945 ds.AddZipEntry(ZIP_ROOT_DIR + path, path);
1946 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001947 DumpIpTablesAsRoot();
David Andersond9ba4752018-12-11 18:26:59 -08001948 DumpDynamicPartitionInfo();
Yifan Hong3945e1b2019-10-29 12:59:23 -07001949 ds.AddDir(OTA_METADATA_DIR, true);
Jeff Sharkey9df29d52023-02-06 14:26:30 -07001950 if (!PropertiesHelper::IsUserBuild()) {
1951 // Include dropbox entry files inside ZIP, but exclude
1952 // noisy WTF and StrictMode entries
1953 dump_files("", DROPBOX_DIR, skip_wtf_strictmode, _add_file_from_fd);
1954 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001955
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001956 // Capture any IPSec policies in play. No keys are exposed here.
Nandana Dutt4be45d12018-09-26 15:04:23 +01001957 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1958
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001959 // Dump IPsec stats. No keys are exposed here.
1960 DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
1961
Nandana Dutt4be45d12018-09-26 15:04:23 +01001962 // Run ss as root so we can see socket marks.
1963 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1964
1965 // Run iotop as root to show top 100 IO threads
1966 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1967
Erick Reyese68df822019-02-11 14:46:36 -08001968 // Gather shared memory buffer info if the product implements it
Hridya Valsaraju1da80c52021-01-09 22:10:11 -08001969 RunCommand("Dmabuf dump", {"dmabuf_dump"});
1970 RunCommand("Dmabuf per-buffer/per-exporter/per-device stats", {"dmabuf_dump", "-b"});
Erick Reyese68df822019-02-11 14:46:36 -08001971
Minchan Kim22c6a1e2019-09-30 15:58:10 -07001972 DumpFile("PSI cpu", "/proc/pressure/cpu");
1973 DumpFile("PSI memory", "/proc/pressure/memory");
1974 DumpFile("PSI io", "/proc/pressure/io");
1975
Steven Moreland9379c462023-12-21 02:04:27 +00001976 ds.AddZipEntry(ZIP_ROOT_DIR + KERNEL_CONFIG, KERNEL_CONFIG);
1977
MÃ¥rten Kongstad60195a72022-09-20 14:14:20 +02001978 RunCommand("SDK EXTENSIONS", {SDK_EXT_INFO, "--dump"},
1979 CommandOptions::WithTimeout(10).Always().DropRoot().Build());
1980
Nattharat Jariyanuntanaetb250cae2024-05-15 07:48:19 +00001981 // Dump UWB UCI logs here because apexdata requires root access
1982 ds.AddDir(UWB_LOG_DIR, true);
1983
Rhed Jao5377d792020-07-16 17:37:39 +08001984 if (dump_pool_) {
1985 RETURN_IF_USER_DENIED_CONSENT();
Chris Morinbc223142022-02-04 14:17:11 -08001986 WaitForTask(std::move(dump_traces));
Rhed Jao5377d792020-07-16 17:37:39 +08001987
Chris Morinbc223142022-02-04 14:17:11 -08001988 // Current running thread in the pool is the root user also. Delete
1989 // the pool and make a new one later to ensure none of threads in the pool are root.
1990 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao5377d792020-07-16 17:37:39 +08001991 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001992 if (!DropRootUser()) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001993 return Dumpstate::RunStatus::ERROR;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001994 }
1995
Nandana Dutt5c390032019-03-12 10:52:56 +00001996 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttdb379fa2019-10-09 16:54:41 +01001997 Dumpstate::RunStatus status = dumpstate();
1998 // Capture logcat since the last time we did it.
1999 DoSystemLogcat(logcat_ts);
2000 return status;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002001}
2002
Rhed Jaob5685b32020-08-14 17:19:17 +08002003// Common states for telephony and wifi which are needed to be collected before
2004// dumpstate drop the root user.
2005static void DumpstateRadioAsRoot() {
2006 DumpIpTablesAsRoot();
2007 ds.AddDir(LOGPERSIST_DATA_DIR, false);
2008}
2009
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002010// This method collects common dumpsys for telephony and wifi. Typically, wifi
2011// reports are fine to include all information, but telephony reports on user
2012// builds need to strip some content (see DumpstateTelephonyOnly).
2013static void DumpstateRadioCommon(bool include_sensitive_info = true) {
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002014 // We need to be picky about some stuff for telephony reports on user builds.
2015 if (!include_sensitive_info) {
2016 // Only dump the radio log buffer (other buffers and dumps contain too much unrelated info).
2017 DoRadioLogcat();
2018 } else {
Rhed Jaob5685b32020-08-14 17:19:17 +08002019 // DumpHals takes long time, post it to the another thread in the pool,
2020 // if pool is available.
Chris Morinbc223142022-02-04 14:17:11 -08002021 std::future<std::string> dump_hals;
Rhed Jaob5685b32020-08-14 17:19:17 +08002022 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002023 dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
Rhed Jaob5685b32020-08-14 17:19:17 +08002024 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002025 // Contains various system properties and process startup info.
2026 do_dmesg();
2027 // Logs other than the radio buffer may contain package/component names and potential PII.
2028 DoLogcat();
2029 // Too broad for connectivity problems.
2030 DoKmsg();
Rhed Jaob5685b32020-08-14 17:19:17 +08002031 // DumpHals contains unrelated hardware info (camera, NFC, biometrics, ...).
2032 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002033 WaitForTask(std::move(dump_hals));
Rhed Jaob5685b32020-08-14 17:19:17 +08002034 } else {
2035 RUN_SLOW_FUNCTION_AND_LOG(DUMP_HALS_TASK, DumpHals);
2036 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002037 }
2038
Jayachandran Ca94c7172017-06-10 15:08:12 -07002039 DumpPacketStats();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002040 DumpIpAddrAndRules();
2041 dump_route_tables();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002042 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
2043 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08002044}
2045
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002046// We use "telephony" here for legacy reasons, though this now really means "connectivity" (cellular
2047// + wifi + networking). This method collects dumpsys for connectivity debugging only. General rules
2048// for what can be included on user builds: all reported information MUST directly relate to
2049// connectivity debugging or customer support and MUST NOT contain unrelated personally identifiable
2050// information. This information MUST NOT identify user-installed packages (UIDs are OK, package
2051// names are not), and MUST NOT contain logs of user application traffic.
2052// TODO(b/148168577) rename this and other related fields/methods to "connectivity" instead.
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08002053static void DumpstateTelephonyOnly(const std::string& calling_package) {
mukesh agrawal253dad42018-01-23 21:59:59 -08002054 DurationReporter duration_reporter("DUMPSTATE");
Jichao Lie89d9c12019-11-21 19:02:51 -08002055
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002056 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
mukesh agrawal253dad42018-01-23 21:59:59 -08002057
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002058 const bool include_sensitive_info = !PropertiesHelper::IsUserBuild();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002059
Rhed Jaob5685b32020-08-14 17:19:17 +08002060 DumpstateRadioAsRoot();
2061 if (!DropRootUser()) {
2062 return;
2063 }
2064
2065 // Starts thread pool after the root user is dropped, and two additional threads
2066 // are created for DumpHals in the DumpstateRadioCommon and DumpstateBoard.
Chris Morinbc223142022-02-04 14:17:11 -08002067 std::future<std::string> dump_board;
Rhed Jaob5685b32020-08-14 17:19:17 +08002068 if (ds.dump_pool_) {
2069 ds.dump_pool_->start(/*thread_counts =*/2);
2070
2071 // DumpstateBoard takes long time, post it to the another thread in the pool,
2072 // if pool is available.
Chris Morinbc223142022-02-04 14:17:11 -08002073 dump_board = ds.dump_pool_->enqueueTaskWithFd(
2074 DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
Rhed Jaob5685b32020-08-14 17:19:17 +08002075 }
2076
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002077 DumpstateRadioCommon(include_sensitive_info);
2078
2079 if (include_sensitive_info) {
2080 // Contains too much unrelated PII, and given the unstructured nature of sysprops, we can't
2081 // really cherrypick all of the connectivity-related ones. Apps generally have no business
2082 // reading these anyway, and there should be APIs to supply the info in a more app-friendly
2083 // way.
2084 RunCommand("SYSTEM PROPERTIES", {"getprop"});
2085 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002086
2087 printf("========================================================\n");
2088 printf("== Android Framework Services\n");
2089 printf("========================================================\n");
2090
Vishnu Nair652cc802017-11-30 15:18:30 -08002091 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2092 SEC_TO_MSEC(10));
Hunter Knepshield31cbae12021-05-11 16:23:24 -07002093 RunDumpsys("DUMPSYS", {"vcn_management"}, CommandOptions::WithTimeout(90).Build(),
2094 SEC_TO_MSEC(10));
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08002095 if (include_sensitive_info) {
2096 // Carrier apps' services will be dumped below in dumpsys activity service all-non-platform.
2097 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
2098 SEC_TO_MSEC(10));
2099 } else {
2100 // If the caller is a carrier app and has a carrier service, dump it here since we aren't
2101 // running dumpsys activity service all-non-platform below. Due to the increased output, we
2102 // give a higher timeout as well.
2103 RunDumpsys("DUMPSYS", {"carrier_config", "--requesting-package", calling_package},
2104 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(30));
2105 }
2106 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002107 RunDumpsys("DUMPSYS", {"netpolicy"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2108 RunDumpsys("DUMPSYS", {"network_management"}, CommandOptions::WithTimeout(90).Build(),
Sooraj Sasindrane8d98912018-04-20 11:31:55 -07002109 SEC_TO_MSEC(10));
Hunter Knepshield0fe51b12020-03-05 16:58:20 -08002110 RunDumpsys("DUMPSYS", {"telephony.registry"}, CommandOptions::WithTimeout(90).Build(),
2111 SEC_TO_MSEC(10));
Jack Yu773cc032023-03-16 22:43:39 -07002112 RunDumpsys("DUMPSYS", {"isub"}, CommandOptions::WithTimeout(90).Build(),
2113 SEC_TO_MSEC(10));
Grant Menke56698972023-02-24 13:11:07 -08002114 RunDumpsys("DUMPSYS", {"telecom"}, CommandOptions::WithTimeout(90).Build(),
2115 SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002116 if (include_sensitive_info) {
2117 // Contains raw IP addresses, omit from reports on user builds.
2118 RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2119 // Contains raw destination IP/MAC addresses, omit from reports on user builds.
2120 RunDumpsys("DUMPSYS", {"connmetrics"}, CommandOptions::WithTimeout(90).Build(),
2121 SEC_TO_MSEC(10));
2122 // Contains package/component names, omit from reports on user builds.
2123 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
2124 SEC_TO_MSEC(10));
2125 // Contains package names, but should be relatively simple to remove them (also contains
2126 // UIDs already), omit from reports on user builds.
2127 RunDumpsys("BATTERYSTATS", {"deviceidle"}, CommandOptions::WithTimeout(90).Build(),
2128 SEC_TO_MSEC(10));
2129 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002130
2131 printf("========================================================\n");
2132 printf("== Running Application Services\n");
2133 printf("========================================================\n");
2134
2135 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
2136
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002137 if (include_sensitive_info) {
2138 printf("========================================================\n");
2139 printf("== Running Application Services (non-platform)\n");
2140 printf("========================================================\n");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002141
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002142 // Contains package/component names and potential PII, omit from reports on user builds.
2143 // To get dumps of the active CarrierService(s) on user builds, we supply an argument to the
2144 // carrier_config dumpsys instead.
2145 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
2146 DUMPSYS_COMPONENTS_OPTIONS);
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002147
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002148 printf("========================================================\n");
2149 printf("== Checkins\n");
2150 printf("========================================================\n");
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002151
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002152 // Contains package/component names, omit from reports on user builds.
2153 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
2154 }
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002155
2156 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07002157 printf("== dumpstate: done (id %d)\n", ds.id_);
2158 printf("========================================================\n");
Rhed Jaob5685b32020-08-14 17:19:17 +08002159
2160 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002161 WaitForTask(std::move(dump_board));
Rhed Jaob5685b32020-08-14 17:19:17 +08002162 } else {
2163 RUN_SLOW_FUNCTION_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
2164 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002165}
2166
mukesh agrawal253dad42018-01-23 21:59:59 -08002167// This method collects dumpsys for wifi debugging only
2168static void DumpstateWifiOnly() {
2169 DurationReporter duration_reporter("DUMPSTATE");
2170
Rhed Jaob5685b32020-08-14 17:19:17 +08002171 DumpstateRadioAsRoot();
2172 if (!DropRootUser()) {
2173 return;
2174 }
2175
2176 // Starts thread pool after the root user is dropped. Only one additional
2177 // thread is needed for DumpHals in the DumpstateRadioCommon.
2178 if (ds.dump_pool_) {
2179 ds.dump_pool_->start(/*thread_counts =*/1);
2180 }
2181
mukesh agrawal253dad42018-01-23 21:59:59 -08002182 DumpstateRadioCommon();
2183
2184 printf("========================================================\n");
2185 printf("== Android Framework Services\n");
2186 printf("========================================================\n");
2187
2188 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2189 SEC_TO_MSEC(10));
2190 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
2191 SEC_TO_MSEC(10));
2192
2193 printf("========================================================\n");
2194 printf("== dumpstate: done (id %d)\n", ds.id_);
2195 printf("========================================================\n");
2196}
2197
Elis Elliott8e401ad2023-08-08 11:18:59 +00002198// Collects a lightweight dumpstate to be used for debugging onboarding related flows.
2199static void DumpstateOnboardingOnly() {
2200 ds.AddDir(LOGPERSIST_DATA_DIR, false);
2201}
2202
Christopher Ferris83e0e842024-05-31 13:13:34 -07002203static std::string GetTimestamp(const timespec& ts) {
2204 tm tm;
2205 localtime_r(&ts.tv_sec, &tm);
2206
2207 // Reserve enough space for the entire time string, includes the space
2208 // for the '\0' to make the calculations below easier by using size for
2209 // the total string size.
2210 std::string str(sizeof("1970-01-01 00:00:00.123456789+0830"), '\0');
2211 size_t n = strftime(str.data(), str.size(), "%F %H:%M", &tm);
2212 if (n == 0) {
2213 return "TIMESTAMP FAILURE";
2214 }
2215 int num_chars = snprintf(&str[n], str.size() - n, ":%02d.%09ld", tm.tm_sec, ts.tv_nsec);
2216 if (num_chars > str.size() - n) {
2217 return "TIMESTAMP FAILURE";
2218 }
2219 n += static_cast<size_t>(num_chars);
2220 if (strftime(&str[n], str.size() - n, "%z", &tm) == 0) {
2221 return "TIMESTAMP FAILURE";
2222 }
2223 return str;
2224}
2225
2226static std::string GetCmdline(pid_t pid) {
2227 std::string cmdline;
2228 if (!android::base::ReadFileToString(android::base::StringPrintf("/proc/%d/cmdline", pid),
2229 &cmdline)) {
2230 return "UNKNOWN";
2231 }
2232 // There are '\0' terminators between arguments, convert them to spaces.
2233 // But start by skipping all trailing '\0' values.
2234 size_t cur = cmdline.size() - 1;
2235 while (cur != 0 && cmdline[cur] == '\0') {
2236 cur--;
2237 }
2238 if (cur == 0) {
2239 return "UNKNOWN";
2240 }
2241 while ((cur = cmdline.rfind('\0', cur)) != std::string::npos) {
2242 cmdline[cur] = ' ';
2243 }
2244 return cmdline;
2245}
2246
2247static void DumpPidHeader(int fd, pid_t pid, const timespec& ts) {
2248 // For consistency, the header to this message matches the one
2249 // dumped by debuggerd.
2250 dprintf(fd, "\n----- pid %d at %s -----\n", pid, GetTimestamp(ts).c_str());
2251 dprintf(fd, "Cmd line: %s\n", GetCmdline(pid).c_str());
2252}
2253
2254static void DumpPidFooter(int fd, pid_t pid) {
2255 // For consistency, the footer to this message matches the one
2256 // dumped by debuggerd.
2257 dprintf(fd, "----- end %d -----\n", pid);
2258}
2259
2260static bool DumpBacktrace(int fd, pid_t pid, bool is_java_process) {
2261 int ret = dump_backtrace_to_file_timeout(
2262 pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace, 3, fd);
2263 if (ret == -1 && is_java_process) {
2264 // Tried to unwind as a java process, try a native unwind.
2265 dprintf(fd, "Java unwind failed for pid %d, trying a native unwind.\n", pid);
2266 ret = dump_backtrace_to_file_timeout(pid, kDebuggerdNativeBacktrace, 3, fd);
2267 }
2268 return ret != -1;
2269}
2270
Nandana Duttcf419a72019-03-14 10:40:17 +00002271Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
Gavin Corkery789d7a52021-02-24 23:52:35 +00002272 const std::string temp_file_pattern = ds.bugreport_internal_dir_ + "/dumptrace_XXXXXX";
Nandana Duttfaafd522019-03-11 09:23:09 +00002273 const size_t buf_size = temp_file_pattern.length() + 1;
2274 std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
2275 memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
2276
2277 // Create a new, empty file to receive all trace dumps.
2278 //
2279 // TODO: This can be simplified once we remove support for the old style
2280 // dumps. We can have a file descriptor passed in to dump_traces instead
2281 // of creating a file, closing it and then reopening it again.
2282 android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
2283 if (fd < 0) {
2284 MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002285 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002286 }
2287
2288 // Nobody should have access to this temporary file except dumpstate, but we
2289 // temporarily grant 'read' to 'others' here because this file is created
2290 // when tombstoned is still running as root, but dumped after dropping. This
2291 // can go away once support for old style dumping has.
2292 const int chmod_ret = fchmod(fd, 0666);
2293 if (chmod_ret < 0) {
2294 MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002295 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002296 }
2297
2298 std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
2299 if (proc.get() == nullptr) {
2300 MYLOGE("opendir /proc failed: %s\n", strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002301 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002302 }
2303
2304 // Number of times process dumping has timed out. If we encounter too many
2305 // failures, we'll give up.
2306 int timeout_failures = 0;
2307 bool dalvik_found = false;
2308
Jayant Chowdharya0a8eb22022-05-20 03:30:09 +00002309 const std::set<int> hal_pids = get_interesting_pids();
Nandana Duttfaafd522019-03-11 09:23:09 +00002310
2311 struct dirent* d;
2312 while ((d = readdir(proc.get()))) {
Nandana Duttcf419a72019-03-14 10:40:17 +00002313 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttfaafd522019-03-11 09:23:09 +00002314 int pid = atoi(d->d_name);
2315 if (pid <= 0) {
2316 continue;
2317 }
2318
2319 const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
2320 std::string exe;
2321 if (!android::base::Readlink(link_name, &exe)) {
2322 continue;
2323 }
2324
2325 bool is_java_process;
2326 if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
2327 // Don't bother dumping backtraces for the zygote.
2328 if (IsZygote(pid)) {
2329 continue;
2330 }
2331
2332 dalvik_found = true;
2333 is_java_process = true;
2334 } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
2335 is_java_process = false;
2336 } else {
2337 // Probably a native process we don't care about, continue.
2338 continue;
2339 }
2340
2341 // If 3 backtrace dumps fail in a row, consider debuggerd dead.
2342 if (timeout_failures == 3) {
2343 dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
2344 break;
2345 }
2346
Christopher Ferris83e0e842024-05-31 13:13:34 -07002347 timespec start_timespec;
2348 clock_gettime(CLOCK_REALTIME, &start_timespec);
2349 if (IsCached(pid)) {
2350 DumpPidHeader(fd, pid, start_timespec);
2351 dprintf(fd, "Process is cached, skipping backtrace due to high chance of timeout.\n");
2352 DumpPidFooter(fd, pid);
2353 continue;
2354 }
Nandana Duttfaafd522019-03-11 09:23:09 +00002355
Christopher Ferris83e0e842024-05-31 13:13:34 -07002356 const uint64_t start = Nanotime();
2357 if (!DumpBacktrace(fd, pid, is_java_process)) {
2358 if (IsCached(pid)) {
2359 DumpPidHeader(fd, pid, start_timespec);
2360 dprintf(fd, "Backtrace failed, but process has become cached.\n");
2361 DumpPidFooter(fd, pid);
2362 continue;
2363 }
2364
2365 DumpPidHeader(fd, pid, start_timespec);
2366 dprintf(fd, "Backtrace gathering failed, likely due to a timeout.\n");
2367 DumpPidFooter(fd, pid);
2368
2369 dprintf(fd, "\n[dump %s stack %d: %.3fs elapsed]\n",
2370 is_java_process ? "dalvik" : "native", pid,
2371 (float)(Nanotime() - start) / NANOS_PER_SEC);
Nandana Duttfaafd522019-03-11 09:23:09 +00002372 timeout_failures++;
2373 continue;
2374 }
2375
2376 // We've successfully dumped stack traces, reset the failure count
2377 // and write a summary of the elapsed time to the file and continue with the
2378 // next process.
2379 timeout_failures = 0;
2380
2381 dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
2382 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
2383 }
2384
2385 if (!dalvik_found) {
2386 MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
2387 }
2388
Nandana Duttcf419a72019-03-14 10:40:17 +00002389 *path = file_name_buf.release();
2390 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002391}
2392
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002393static dumpstate_hal_hidl::DumpstateMode GetDumpstateHalModeHidl(
2394 const Dumpstate::BugreportMode bugreport_mode) {
2395 switch (bugreport_mode) {
2396 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2397 return dumpstate_hal_hidl::DumpstateMode::FULL;
2398 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2399 return dumpstate_hal_hidl::DumpstateMode::INTERACTIVE;
2400 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2401 return dumpstate_hal_hidl::DumpstateMode::REMOTE;
2402 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2403 return dumpstate_hal_hidl::DumpstateMode::WEAR;
2404 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2405 return dumpstate_hal_hidl::DumpstateMode::CONNECTIVITY;
2406 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2407 return dumpstate_hal_hidl::DumpstateMode::WIFI;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002408 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002409 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2410 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2411 }
2412 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2413}
2414
2415static dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode GetDumpstateHalModeAidl(
2416 const Dumpstate::BugreportMode bugreport_mode) {
2417 switch (bugreport_mode) {
2418 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2419 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::FULL;
2420 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2421 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::INTERACTIVE;
2422 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2423 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::REMOTE;
2424 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2425 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WEAR;
2426 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2427 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::CONNECTIVITY;
2428 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2429 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WIFI;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002430 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002431 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2432 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2433 }
2434 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2435}
2436
2437static void DoDumpstateBoardHidl(
2438 const sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_1_0,
2439 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2440 const Dumpstate::BugreportMode bugreport_mode,
2441 const size_t timeout_sec) {
2442
2443 using ScopedNativeHandle =
2444 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
2445 ScopedNativeHandle handle(native_handle_create(static_cast<int>(dumpstate_fds.size()), 0),
2446 [](native_handle_t* handle) {
2447 // we don't close file handle's here
2448 // via native_handle_close(handle)
2449 // instead we let dumpstate_fds close the file handles when
2450 // dumpstate_fds gets destroyed
2451 native_handle_delete(handle);
2452 });
2453 if (handle == nullptr) {
2454 MYLOGE("Could not create native_handle for dumpstate HAL\n");
2455 return;
2456 }
2457
2458 for (size_t i = 0; i < dumpstate_fds.size(); i++) {
2459 handle.get()->data[i] = dumpstate_fds[i].get();
2460 }
2461
2462 // Prefer version 1.1 if available. New devices launching with R are no longer allowed to
2463 // implement just 1.0.
2464 const char* descriptor_to_kill;
2465 using DumpstateBoardTask = std::packaged_task<bool()>;
2466 DumpstateBoardTask dumpstate_board_task;
2467 sp<dumpstate_hal_hidl::IDumpstateDevice> dumpstate_hal(
2468 dumpstate_hal_hidl::IDumpstateDevice::castFrom(dumpstate_hal_1_0));
2469 if (dumpstate_hal != nullptr) {
2470 MYLOGI("Using IDumpstateDevice v1.1 HIDL HAL");
2471
2472 dumpstate_hal_hidl::DumpstateMode dumpstate_hal_mode =
2473 GetDumpstateHalModeHidl(bugreport_mode);
2474
2475 descriptor_to_kill = dumpstate_hal_hidl::IDumpstateDevice::descriptor;
2476 dumpstate_board_task =
2477 DumpstateBoardTask([timeout_sec, dumpstate_hal_mode, dumpstate_hal, &handle]() -> bool {
2478 ::android::hardware::Return<dumpstate_hal_hidl::DumpstateStatus> status =
2479 dumpstate_hal->dumpstateBoard_1_1(handle.get(), dumpstate_hal_mode,
2480 SEC_TO_MSEC(timeout_sec));
2481 if (!status.isOk()) {
2482 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2483 return false;
2484 } else if (status != dumpstate_hal_hidl::DumpstateStatus::OK) {
2485 MYLOGE("dumpstateBoard failed with DumpstateStatus::%s\n",
2486 dumpstate_hal_hidl::toString(status).c_str());
2487 return false;
2488 }
2489 return true;
2490 });
2491 } else {
2492 MYLOGI("Using IDumpstateDevice v1.0 HIDL HAL");
2493
2494 descriptor_to_kill = dumpstate_hal_hidl_1_0::IDumpstateDevice::descriptor;
2495 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal_1_0, &handle]() -> bool {
2496 ::android::hardware::Return<void> status =
2497 dumpstate_hal_1_0->dumpstateBoard(handle.get());
2498 if (!status.isOk()) {
2499 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2500 return false;
2501 }
2502 return true;
2503 });
2504 }
2505 auto result = dumpstate_board_task.get_future();
2506 std::thread(std::move(dumpstate_board_task)).detach();
2507
2508 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2509 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2510 if (!android::base::SetProperty(
2511 "ctl.interface_restart",
2512 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2513 MYLOGE("Couldn't restart dumpstate HAL\n");
2514 }
2515 }
2516 // Wait some time for init to kill dumpstate vendor HAL
2517 constexpr size_t killing_timeout_sec = 10;
2518 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2519 MYLOGE(
2520 "killing dumpstateBoard timed out after %zus, continue and "
2521 "there might be racing in content\n",
2522 killing_timeout_sec);
2523 }
2524}
2525
2526static void DoDumpstateBoardAidl(
2527 const std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal,
2528 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2529 const Dumpstate::BugreportMode bugreport_mode, const size_t timeout_sec) {
2530 MYLOGI("Using IDumpstateDevice AIDL HAL");
2531
2532 const char* descriptor_to_kill;
2533 using DumpstateBoardTask = std::packaged_task<bool()>;
2534 DumpstateBoardTask dumpstate_board_task;
2535 dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode dumpstate_hal_mode =
2536 GetDumpstateHalModeAidl(bugreport_mode);
2537
2538 descriptor_to_kill = dumpstate_hal_aidl::IDumpstateDevice::descriptor;
2539 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal, &dumpstate_fds, dumpstate_hal_mode,
2540 timeout_sec]() -> bool {
2541 auto status = dumpstate_hal->dumpstateBoard(dumpstate_fds, dumpstate_hal_mode, timeout_sec);
2542
2543 if (!status.isOk()) {
2544 MYLOGE("dumpstateBoard failed: %s\n", status.getDescription().c_str());
2545 return false;
2546 }
2547 return true;
2548 });
2549 auto result = dumpstate_board_task.get_future();
2550 std::thread(std::move(dumpstate_board_task)).detach();
2551
2552 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2553 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2554 if (!android::base::SetProperty(
2555 "ctl.interface_restart",
2556 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2557 MYLOGE("Couldn't restart dumpstate HAL\n");
2558 }
2559 }
2560 // Wait some time for init to kill dumpstate vendor HAL
2561 constexpr size_t killing_timeout_sec = 10;
2562 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2563 MYLOGE(
2564 "killing dumpstateBoard timed out after %zus, continue and "
2565 "there might be racing in content\n",
2566 killing_timeout_sec);
2567 }
2568}
2569
2570static std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> GetDumpstateBoardAidlService() {
2571 const std::string aidl_instance_name =
2572 std::string(dumpstate_hal_aidl::IDumpstateDevice::descriptor) + "/default";
2573
2574 if (!AServiceManager_isDeclared(aidl_instance_name.c_str())) {
2575 return nullptr;
2576 }
2577
2578 ndk::SpAIBinder dumpstateBinder(AServiceManager_waitForService(aidl_instance_name.c_str()));
2579
2580 return dumpstate_hal_aidl::IDumpstateDevice::fromBinder(dumpstateBinder);
2581}
2582
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002583void Dumpstate::DumpstateBoard(int out_fd) {
2584 dprintf(out_fd, "========================================================\n");
2585 dprintf(out_fd, "== Board\n");
2586 dprintf(out_fd, "========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08002587
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002588 /*
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002589 * mount debugfs for non-user builds with ro.product.debugfs_restrictions.enabled
Hridya Valsaraju51101602021-04-02 14:32:46 -07002590 * set to true and unmount it after invoking dumpstateBoard_* methods.
2591 * This is to enable debug builds to not have debugfs mounted during runtime.
2592 * It will also ensure that debugfs is only accessed by the dumpstate HAL.
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002593 */
Hridya Valsaraju51101602021-04-02 14:32:46 -07002594 auto mount_debugfs =
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002595 android::base::GetBoolProperty("ro.product.debugfs_restrictions.enabled", false);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002596 if (mount_debugfs) {
2597 RunCommand("mount debugfs", {"mount", "-t", "debugfs", "debugfs", "/sys/kernel/debug"},
2598 AS_ROOT_20);
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002599 RunCommand("chmod debugfs", {"chmod", "0755", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002600 }
2601
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002602 std::vector<std::string> paths;
2603 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07002604 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002605 paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
2606 kDumpstateBoardFiles[i].c_str()));
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002607 remover.emplace_back(android::base::make_scope_guard(
2608 std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002609 }
Jie Song9fbfad02017-06-20 16:29:42 -07002610
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002611 // get dumpstate HAL AIDL implementation
2612 std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal_handle_aidl(
2613 GetDumpstateBoardAidlService());
2614 if (dumpstate_hal_handle_aidl == nullptr) {
2615 MYLOGI("No IDumpstateDevice AIDL implementation\n");
2616 }
2617
2618 // get dumpstate HAL HIDL implementation, only if AIDL HAL implementation not found
2619 sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_handle_hidl_1_0 = nullptr;
2620 if (dumpstate_hal_handle_aidl == nullptr) {
2621 dumpstate_hal_handle_hidl_1_0 = dumpstate_hal_hidl_1_0::IDumpstateDevice::getService();
2622 if (dumpstate_hal_handle_hidl_1_0 == nullptr) {
2623 MYLOGI("No IDumpstateDevice HIDL implementation\n");
2624 }
2625 }
2626
2627 // if neither HIDL nor AIDL implementation found, then return
2628 if (dumpstate_hal_handle_hidl_1_0 == nullptr && dumpstate_hal_handle_aidl == nullptr) {
2629 MYLOGE("Could not find IDumpstateDevice implementation\n");
Wei Wang587eac92018-04-05 12:17:20 -07002630 return;
2631 }
2632
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002633 // this is used to hold the file descriptors and when this variable goes out of scope
2634 // the file descriptors are closed
2635 std::vector<::ndk::ScopedFileDescriptor> dumpstate_fds;
Wei Wang587eac92018-04-05 12:17:20 -07002636
Nandana Dutt5c390032019-03-12 10:52:56 +00002637 // TODO(128270426): Check for consent in between?
Wei Wang587eac92018-04-05 12:17:20 -07002638 for (size_t i = 0; i < paths.size(); i++) {
2639 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
2640
2641 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
2642 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
2643 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
2644 if (fd < 0) {
2645 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
2646 return;
2647 }
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002648
2649 dumpstate_fds.emplace_back(fd.release());
2650 // we call fd.release() here to make sure "fd" does not get closed
2651 // after "fd" goes out of scope after this block.
2652 // "fd" will be closed when "dumpstate_fds" goes out of scope
2653 // i.e. when we exit this function
Wei Wang587eac92018-04-05 12:17:20 -07002654 }
2655
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002656 // Given that bugreport is required to diagnose failures, it's better to set an arbitrary amount
2657 // of timeout for IDumpstateDevice than to block the rest of bugreport. In the timeout case, we
2658 // will kill the HAL and grab whatever it dumped in time.
Michael Eastwood8523ea02022-03-10 16:33:08 -08002659 constexpr size_t timeout_sec = 45;
Wei Wang587eac92018-04-05 12:17:20 -07002660
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002661 if (dumpstate_hal_handle_aidl != nullptr) {
2662 DoDumpstateBoardAidl(dumpstate_hal_handle_aidl, dumpstate_fds, options_->bugreport_mode,
2663 timeout_sec);
2664 } else if (dumpstate_hal_handle_hidl_1_0 != nullptr) {
2665 // run HIDL HAL only if AIDL HAL not found
2666 DoDumpstateBoardHidl(dumpstate_hal_handle_hidl_1_0, dumpstate_fds, options_->bugreport_mode,
2667 timeout_sec);
Wei Wang587eac92018-04-05 12:17:20 -07002668 }
2669
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002670 if (mount_debugfs) {
Hridya Valsaraju51101602021-04-02 14:32:46 -07002671 auto keep_debugfs_mounted =
2672 android::base::GetProperty("persist.dbg.keep_debugfs_mounted", "");
2673 if (keep_debugfs_mounted.empty())
2674 RunCommand("unmount debugfs", {"umount", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002675 }
2676
Wei Wang587eac92018-04-05 12:17:20 -07002677 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
2678 for (size_t i = 0; i < paths.size(); i++) {
2679 struct stat s;
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002680 if (fstat(dumpstate_fds[i].get(), &s) == -1) {
2681 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(), strerror(errno));
Wei Wang587eac92018-04-05 12:17:20 -07002682 file_sizes[i] = -1;
2683 continue;
2684 }
2685 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002686 }
2687
2688 for (size_t i = 0; i < paths.size(); i++) {
2689 if (file_sizes[i] == -1) {
2690 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002691 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002692 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07002693 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002694 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002695 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002696 remover[i].Disable();
2697 EnqueueAddZipEntryAndCleanupIfNeeded(kDumpstateBoardFiles[i], paths[i]);
2698 dprintf(out_fd, "*** See %s entry ***\n", kDumpstateBoardFiles[i].c_str());
Jie Song9fbfad02017-06-20 16:29:42 -07002699 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08002700}
2701
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002702static void ShowUsage() {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002703 fprintf(stderr,
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002704 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o directory] [-p] "
2705 "[-s] [-S] [-q] [-P] [-R] [-L] [-V version]\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002706 " -h: display this help message\n"
2707 " -b: play sound file instead of vibrate, at beginning of job\n"
2708 " -e: play sound file instead of vibrate, at end of job\n"
mhasank2d75c442020-06-11 15:05:25 -07002709 " -o: write to custom directory (only in limited mode)\n"
Abhijeet Kaurbb55a3b2019-06-13 18:07:25 +01002710 " -p: capture screenshot to filename.png\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002711 " -s: write zipped file to control socket (for init)\n"
2712 " -S: write file location to control socket (for init)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002713 " -q: disable vibrate\n"
Abhijeet Kaure370d682019-10-01 16:49:30 +01002714 " -P: send broadcast when started and do progress updates\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002715 " -R: take bugreport in remote mode (shouldn't be used with -P)\n"
Nandana Dutt235864b2019-01-22 12:10:16 +00002716 " -w: start binder service and make it wait for a call to startBugreport\n"
mhasankd451a472020-05-26 18:02:39 -07002717 " -L: output limited information that is safe for submission in feedback reports\n"
Felipe Lemed071c682016-10-20 16:48:00 -07002718 " -v: prints the dumpstate header and exit\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002719}
2720
Wei Liuf87959e2016-08-26 14:51:42 -07002721static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07002722 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07002723}
2724
Felipe Leme1d486fe2016-10-14 18:06:47 -07002725bool Dumpstate::FinishZipFile() {
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002726 // Runs all enqueued adding zip entry and cleanup tasks before finishing the zip file.
2727 if (zip_entry_tasks_) {
2728 zip_entry_tasks_->run(/* do_cancel = */false);
2729 }
2730
Felipe Leme9a523ae2016-10-20 15:10:33 -07002731 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07002732 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07002733 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002734 // Final timestamp
2735 char date[80];
2736 time_t the_real_now_please_stand_up = time(nullptr);
2737 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002738 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002739 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002740
Felipe Leme9a523ae2016-10-20 15:10:33 -07002741 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002742 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08002743 return false;
2744 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07002745 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002746 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08002747 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08002748 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08002749
Felipe Leme0f3fb202016-06-10 17:10:53 -07002750 // Add log file (which contains stderr output) to zip...
2751 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002752 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07002753 MYLOGE("Failed to add dumpstate log to .zip file\n");
2754 return false;
2755 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002756 // TODO: Should truncate the existing file.
2757 // ... and re-open it for further logging.
Nandana Dutta344cb62019-02-22 15:12:35 +00002758 if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
2759 return false;
2760 }
Felipe Leme0f3fb202016-06-10 17:10:53 -07002761 fprintf(stderr, "\n");
2762
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002763 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07002764 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002765 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002766 return false;
2767 }
2768
Felipe Leme1d486fe2016-10-14 18:06:47 -07002769 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
2770 ds.zip_file.reset(nullptr);
2771
Felipe Lemee9d2c542016-11-15 11:48:26 -08002772 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002773 android::os::UnlinkAndLogOnError(tmp_path_);
Felipe Lemec4eee562016-04-21 15:42:55 -07002774
Felipe Leme1e9edc62015-12-21 16:02:13 -08002775 return true;
2776}
Felipe Leme6e01fa62015-11-11 19:35:14 -08002777
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00002778static void SendBroadcast(const std::string& action,
2779 const std::vector<std::string>& args,
2780 int32_t user_id) {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002781 // clang-format off
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00002782 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user",
2783 std::to_string(user_id), "--receiver-foreground",
2784 "--receiver-include-background", "-a", action};
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002785 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08002786
2787 am.insert(am.end(), args.begin(), args.end());
2788
Felipe Leme8d2410e2017-02-08 09:46:08 -08002789 RunCommand("", am,
2790 CommandOptions::WithTimeout(20)
2791 .Log("Sending broadcast: '%s'\n")
2792 .Always()
2793 .DropRoot()
2794 .RedirectStderr()
2795 .Build());
2796}
2797
Felipe Leme35b8cf12017-02-10 15:47:29 -08002798static void Vibrate(int duration_ms) {
2799 // clang-format off
Lais Andrade51156962021-02-22 19:21:35 +00002800 std::vector<std::string> args = {"cmd", "vibrator_manager", "synced", "-f", "-d", "dumpstate",
2801 "oneshot", std::to_string(duration_ms)};
2802 RunCommand("", args,
Felipe Leme35b8cf12017-02-10 15:47:29 -08002803 CommandOptions::WithTimeout(10)
2804 .Log("Vibrate: '%s'\n")
2805 .Always()
2806 .Build());
2807 // clang-format on
2808}
2809
Nandana Dutt979388e2018-11-30 16:48:55 +00002810static void MaybeResolveSymlink(std::string* path) {
2811 std::string resolved_path;
2812 if (android::base::Readlink(*path, &resolved_path)) {
2813 *path = resolved_path;
2814 }
2815}
2816
Nandana Dutt4be45d12018-09-26 15:04:23 +01002817/*
2818 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002819 * and adds the version file. Return false if zip_file could not be open to write.
Nandana Dutt4be45d12018-09-26 15:04:23 +01002820 */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002821static bool PrepareToWriteToFile() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002822 MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2823
Nandana Dutt4be45d12018-09-26 15:04:23 +01002824 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2825 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002826 ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002827 char date[80];
2828 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2829 ds.name_ = date;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002830
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002831 if (ds.options_->telephony_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002832 ds.base_name_ += "-telephony";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002833 } else if (ds.options_->wifi_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002834 ds.base_name_ += "-wifi";
2835 }
2836
Paul Chang0d2aad72020-02-13 20:04:03 +08002837 if (ds.options_->do_screenshot) {
Nandana Dutt9d17b942020-03-26 10:02:59 +00002838 ds.screenshot_path_ = ds.GetPath(ds.CalledByApi() ? "-png.tmp" : ".png");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002839 }
2840 ds.tmp_path_ = ds.GetPath(".tmp");
2841 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2842
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01002843 std::string destination = ds.CalledByApi()
Nandana Dutt54dbd672019-01-11 12:58:05 +00002844 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
Nandana Dutt9a76d202019-01-21 15:56:48 +00002845 : ds.bugreport_internal_dir_.c_str();
Nandana Dutt4be45d12018-09-26 15:04:23 +01002846 MYLOGD(
Nandana Dutt235c6672019-11-14 15:22:32 +00002847 "Bugreport dir: [%s] "
2848 "Base name: [%s] "
2849 "Suffix: [%s] "
2850 "Log path: [%s] "
2851 "Temporary path: [%s] "
2852 "Screenshot path: [%s]\n",
Nandana Dutt9a76d202019-01-21 15:56:48 +00002853 destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2854 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002855
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002856 ds.path_ = ds.GetPath(ds.CalledByApi() ? "-zip.tmp" : ".zip");
2857 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2858 create_parent_dirs(ds.path_.c_str());
2859 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2860 if (ds.zip_file == nullptr) {
2861 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2862 return false;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002863 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002864 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2865 ds.AddTextZipEntry("version.txt", ds.version_);
2866 return true;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002867}
2868
2869/*
Abhijeet Kaure370d682019-10-01 16:49:30 +01002870 * Finalizes writing to the file by zipping the tmp file to the final location,
Nandana Dutt4be45d12018-09-26 15:04:23 +01002871 * printing zipped file status, etc.
2872 */
2873static void FinalizeFile() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002874 bool do_text_file = !ds.FinishZipFile();
2875 if (do_text_file) {
2876 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002877 }
mhasank2d75c442020-06-11 15:05:25 -07002878
2879 std::string final_path = ds.path_;
2880 if (ds.options_->OutputToCustomFile()) {
mhasank3a4cfb42020-06-15 18:06:43 -07002881 final_path = ds.GetPath(ds.options_->out_dir, ".zip");
mhasank2d75c442020-06-11 15:05:25 -07002882 android::os::CopyFileToFile(ds.path_, final_path);
2883 }
2884
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002885 if (ds.options_->stream_to_socket) {
2886 android::os::CopyFileToFd(ds.path_, ds.control_socket_fd_);
2887 } else if (ds.options_->progress_updates_to_socket) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002888 if (do_text_file) {
2889 dprintf(ds.control_socket_fd_,
2890 "FAIL:could not create zip file, check %s "
2891 "for more details\n",
2892 ds.log_path_.c_str());
2893 } else {
mhasank2d75c442020-06-11 15:05:25 -07002894 dprintf(ds.control_socket_fd_, "OK:%s\n", final_path.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002895 }
2896 }
2897}
2898
Nandana Dutt4be45d12018-09-26 15:04:23 +01002899
Nandana Dutt58d72e22018-11-16 10:30:48 +00002900static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2901 switch (mode) {
2902 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2903 return "BUGREPORT_FULL";
2904 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2905 return "BUGREPORT_INTERACTIVE";
2906 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2907 return "BUGREPORT_REMOTE";
2908 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2909 return "BUGREPORT_WEAR";
2910 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2911 return "BUGREPORT_TELEPHONY";
2912 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2913 return "BUGREPORT_WIFI";
Elis Elliott8e401ad2023-08-08 11:18:59 +00002914 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
2915 return "BUGREPORT_ONBOARDING";
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002916 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2917 return "BUGREPORT_DEFAULT";
Nandana Dutt58d72e22018-11-16 10:30:48 +00002918 }
2919}
2920
Steven Leeb573eb82022-11-29 22:31:35 +08002921static bool IsConsentlessBugreportAllowed(const Dumpstate::DumpOptions& options) {
2922 // only BUGREPORT_TELEPHONY does not allow using consentless bugreport
2923 return !options.telephony_only;
2924}
2925
Paul Changf59c2b72020-03-10 02:08:55 +08002926static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options,
2927 bool is_screenshot_requested) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002928 // Modify com.android.shell.BugreportProgressService#isDefaultScreenshotRequired as well for
2929 // default system screenshots.
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002930 options->bugreport_mode = mode;
2931 options->bugreport_mode_string = ModeToString(mode);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002932 switch (mode) {
2933 case Dumpstate::BugreportMode::BUGREPORT_FULL:
Paul Changf59c2b72020-03-10 02:08:55 +08002934 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002935 break;
2936 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002937 // Currently, the dumpstate binder is only used by Shell to update progress.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002938 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002939 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002940 break;
2941 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002942 options->do_vibrate = false;
2943 options->is_remote_mode = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002944 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002945 break;
2946 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
Robert Ginda55ecebd2023-04-03 22:53:13 +00002947 options->do_vibrate = false;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002948 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002949 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002950 break;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002951 // TODO(b/148168577) rename TELEPHONY everywhere to CONNECTIVITY.
Nandana Dutt58d72e22018-11-16 10:30:48 +00002952 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002953 options->telephony_only = true;
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002954 options->do_progress_updates = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002955 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002956 break;
2957 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002958 options->wifi_only = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002959 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002960 break;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002961 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
2962 options->onboarding_only = true;
2963 options->do_screenshot = false;
2964 break;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002965 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2966 break;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002967 }
2968}
2969
Nandana Dutt58d72e22018-11-16 10:30:48 +00002970static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
Nandana Dutt235c6672019-11-14 15:22:32 +00002971 MYLOGI(
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002972 "do_vibrate: %d stream_to_socket: %d progress_updates_to_socket: %d do_screenshot: %d "
Rhed Jao25f50e02020-08-20 00:10:32 +08002973 "is_remote_mode: %d show_header_only: %d telephony_only: %d "
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002974 "wifi_only: %d do_progress_updates: %d fd: %d bugreport_mode: %s "
mhasankd451a472020-05-26 18:02:39 -07002975 "limited_only: %d args: %s\n",
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002976 options.do_vibrate, options.stream_to_socket, options.progress_updates_to_socket,
Paul Chang0d2aad72020-02-13 20:04:03 +08002977 options.do_screenshot, options.is_remote_mode, options.show_header_only,
Rhed Jao25f50e02020-08-20 00:10:32 +08002978 options.telephony_only, options.wifi_only,
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002979 options.do_progress_updates, options.bugreport_fd.get(),
2980 options.bugreport_mode_string.c_str(),
2981 options.limited_only, options.args.c_str());
Nandana Dutt58d72e22018-11-16 10:30:48 +00002982}
2983
Nandana Dutt54dbd672019-01-11 12:58:05 +00002984void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
Kean Mariotti306633e2022-09-05 16:30:47 +00002985 int bugreport_flags,
Nandana Dutt54dbd672019-01-11 12:58:05 +00002986 const android::base::unique_fd& bugreport_fd_in,
Paul Changf59c2b72020-03-10 02:08:55 +08002987 const android::base::unique_fd& screenshot_fd_in,
Kholoud Mohameddef4e432024-05-15 12:47:46 +00002988 bool is_screenshot_requested,
2989 bool skip_user_consent) {
Kean Mariotti306633e2022-09-05 16:30:47 +00002990 this->use_predumped_ui_data = bugreport_flags & BugreportFlag::BUGREPORT_USE_PREDUMPED_UI_DATA;
Gavin Corkerya44686c2022-11-23 18:16:51 +00002991 this->is_consent_deferred = bugreport_flags & BugreportFlag::BUGREPORT_FLAG_DEFER_CONSENT;
Kholoud Mohameddef4e432024-05-15 12:47:46 +00002992 this->skip_user_consent = skip_user_consent;
Nandana Dutt54dbd672019-01-11 12:58:05 +00002993 // Duplicate the fds because the passed in fds don't outlive the binder transaction.
Todd Frederick621533f2022-03-26 02:54:17 +00002994 bugreport_fd.reset(fcntl(bugreport_fd_in.get(), F_DUPFD_CLOEXEC, 0));
2995 screenshot_fd.reset(fcntl(screenshot_fd_in.get(), F_DUPFD_CLOEXEC, 0));
Nandana Dutt58d72e22018-11-16 10:30:48 +00002996
Paul Changf59c2b72020-03-10 02:08:55 +08002997 SetOptionsFromMode(bugreport_mode, this, is_screenshot_requested);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002998}
2999
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003000Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
3001 RunStatus status = RunStatus::OK;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003002 int c;
mhasankd451a472020-05-26 18:02:39 -07003003 while ((c = getopt(argc, argv, "dho:svqzpLPBRSV:w")) != -1) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003004 switch (c) {
3005 // clang-format off
mhasank3a4cfb42020-06-15 18:06:43 -07003006 case 'o': out_dir = optarg; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003007 case 's': stream_to_socket = true; break;
3008 case 'S': progress_updates_to_socket = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003009 case 'v': show_header_only = true; break;
3010 case 'q': do_vibrate = false; break;
Paul Chang0d2aad72020-02-13 20:04:03 +08003011 case 'p': do_screenshot = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003012 case 'P': do_progress_updates = true; break;
3013 case 'R': is_remote_mode = true; break;
mhasankd451a472020-05-26 18:02:39 -07003014 case 'L': limited_only = true; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003015 case 'V':
3016 case 'd':
3017 case 'z':
3018 // compatibility no-op
3019 break;
Nandana Dutt235864b2019-01-22 12:10:16 +00003020 case 'w':
3021 // This was already processed
3022 break;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003023 case 'h':
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003024 status = RunStatus::HELP;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003025 break;
3026 default:
3027 fprintf(stderr, "Invalid option: %c\n", c);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003028 status = RunStatus::INVALID_INPUT;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003029 break;
3030 // clang-format on
3031 }
3032 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08003033
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003034 for (int i = 0; i < argc; i++) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003035 args += argv[i];
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003036 if (i < argc - 1) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003037 args += " ";
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003038 }
3039 }
3040
3041 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
3042 optind = 1;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003043
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003044 return status;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003045}
3046
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003047bool Dumpstate::DumpOptions::ValidateOptions() const {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003048 if (bugreport_fd.get() != -1 && stream_to_socket) {
Nandana Dutt979388e2018-11-30 16:48:55 +00003049 return false;
3050 }
3051
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003052 if ((progress_updates_to_socket || do_progress_updates) && stream_to_socket) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003053 return false;
3054 }
3055
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003056 if (is_remote_mode && (do_progress_updates || stream_to_socket)) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003057 return false;
3058 }
3059 return true;
3060}
3061
Nandana Dutt197661d2018-11-16 16:40:21 +00003062void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
3063 options_ = std::move(options);
3064}
3065
Abhijeet Kaura407fb82020-03-27 12:51:12 +00003066void Dumpstate::Initialize() {
3067 /* gets the sequential id */
3068 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
3069 id_ = ++last_id;
3070 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
3071}
3072
Nandana Duttd2f5f082019-01-18 17:13:52 +00003073Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
3074 Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
Gavin Corkerya44686c2022-11-23 18:16:51 +00003075 HandleRunStatus(status);
3076 return status;
3077}
3078
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003079Dumpstate::RunStatus Dumpstate::Retrieve(int32_t calling_uid, const std::string& calling_package,
Kholoud Mohameddef4e432024-05-15 12:47:46 +00003080 const bool keep_bugreport_on_retrieval,
3081 const bool skip_user_consent) {
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003082 Dumpstate::RunStatus status = RetrieveInternal(calling_uid, calling_package,
Kholoud Mohameddef4e432024-05-15 12:47:46 +00003083 keep_bugreport_on_retrieval,
3084 skip_user_consent);
Gavin Corkerya44686c2022-11-23 18:16:51 +00003085 HandleRunStatus(status);
3086 return status;
3087}
3088
3089Dumpstate::RunStatus Dumpstate::RetrieveInternal(int32_t calling_uid,
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003090 const std::string& calling_package,
Kholoud Mohameddef4e432024-05-15 12:47:46 +00003091 const bool keep_bugreport_on_retrieval,
3092 const bool skip_user_consent) {
3093 if (!android::app::admin::flags::onboarding_consentless_bugreports() || !skip_user_consent) {
3094 consent_callback_ = new ConsentCallback();
3095 const String16 incidentcompanion("incidentcompanion");
3096 sp<android::IBinder> ics(
3097 defaultServiceManager()->checkService(incidentcompanion));
3098 android::String16 package(calling_package.c_str());
3099 if (ics != nullptr) {
3100 MYLOGD("Checking user consent via incidentcompanion service\n");
3101
3102 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
3103 calling_uid, package, String16(), String16(),
3104 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
3105 } else {
3106 MYLOGD(
3107 "Unable to check user consent; incidentcompanion service unavailable\n");
3108 return RunStatus::USER_CONSENT_TIMED_OUT;
3109 }
3110 UserConsentResult consent_result = consent_callback_->getResult();
3111 int timeout_ms = 30 * 1000;
3112 while (consent_result == UserConsentResult::UNAVAILABLE &&
3113 consent_callback_->getElapsedTimeMs() < timeout_ms) {
3114 sleep(1);
3115 consent_result = consent_callback_->getResult();
3116 }
3117 if (consent_result == UserConsentResult::DENIED) {
3118 return RunStatus::USER_CONSENT_DENIED;
3119 }
3120 if (consent_result == UserConsentResult::UNAVAILABLE) {
3121 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3122 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3123 consent_callback_.get());
3124 return RunStatus::USER_CONSENT_TIMED_OUT;
3125 }
Gavin Corkerya44686c2022-11-23 18:16:51 +00003126 }
3127
3128 bool copy_succeeded =
3129 android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003130
3131 if (copy_succeeded && (!android::app::admin::flags::onboarding_bugreport_v2_enabled()
3132 || !keep_bugreport_on_retrieval)) {
3133 android::os::UnlinkAndLogOnError(path_);
Gavin Corkerya44686c2022-11-23 18:16:51 +00003134 }
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003135
Gavin Corkerya44686c2022-11-23 18:16:51 +00003136 return copy_succeeded ? Dumpstate::RunStatus::OK
3137 : Dumpstate::RunStatus::ERROR;
3138}
3139
3140void Dumpstate::HandleRunStatus(Dumpstate::RunStatus status) {
3141 if (listener_ != nullptr) {
Nandana Duttbabf6c72019-01-15 14:11:12 +00003142 switch (status) {
3143 case Dumpstate::RunStatus::OK:
Gavin Corkerya44686c2022-11-23 18:16:51 +00003144 listener_->onFinished(path_.c_str());
Nandana Duttbabf6c72019-01-15 14:11:12 +00003145 break;
3146 case Dumpstate::RunStatus::HELP:
3147 break;
3148 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003149 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00003150 break;
3151 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003152 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
3153 break;
3154 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3155 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
3156 break;
3157 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
3158 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00003159 break;
3160 }
3161 }
Nandana Duttbabf6c72019-01-15 14:11:12 +00003162}
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003163void Dumpstate::Cancel() {
3164 CleanupTmpFiles();
3165 android::os::UnlinkAndLogOnError(log_path_);
3166 for (int i = 0; i < NUM_OF_DUMPS; i++) {
3167 android::os::UnlinkAndLogOnError(ds.bugreport_internal_dir_ + "/" +
3168 kDumpstateBoardFiles[i]);
3169 }
3170 tombstone_data_.clear();
3171 anr_data_.clear();
Andy Hungd62f7e62024-01-11 15:47:52 -08003172 anr_trace_data_.clear();
Woody Lin20767a92022-11-29 15:50:24 +08003173 shutdown_checkpoints_.clear();
Rhed Jao0daac912020-08-21 14:48:20 +08003174
3175 // Instead of shutdown the pool, we delete temporary files directly since
3176 // shutdown blocking the call.
3177 if (dump_pool_) {
3178 dump_pool_->deleteTempFiles();
3179 }
3180 if (zip_entry_tasks_) {
3181 zip_entry_tasks_->run(/*do_cancel =*/ true);
3182 }
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003183}
3184
Kean Mariotti306633e2022-09-05 16:30:47 +00003185void Dumpstate::PreDumpUiData() {
Kean Mariottica20f2d2023-12-15 09:34:25 +00003186 auto snapshot_system_trace = MaybeSnapshotSystemTraceAsync();
Kean Mariotti306633e2022-09-05 16:30:47 +00003187 MaybeSnapshotUiTraces();
Kean Mariottica20f2d2023-12-15 09:34:25 +00003188 MaybeWaitForSnapshotSystemTrace(std::move(snapshot_system_trace));
Kean Mariotti306633e2022-09-05 16:30:47 +00003189}
3190
Nandana Dutt979388e2018-11-30 16:48:55 +00003191/*
3192 * Dumps relevant information to a bugreport based on the given options.
3193 *
3194 * The bugreport can be dumped to a file or streamed to a socket.
3195 *
3196 * How dumping to file works:
3197 * stdout is redirected to a temporary file. This will later become the main bugreport entry.
3198 * stderr is redirected a log file.
3199 *
3200 * The temporary bugreport is then populated via printfs, dumping contents of files and
3201 * output of commands to stdout.
3202 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003203 * A bunch of other files and dumps are added to the zip archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00003204 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003205 * The temporary bugreport file and the log file also get added to the archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00003206 *
mhasank2d75c442020-06-11 15:05:25 -07003207 * Bugreports are first generated in a local directory and later copied to the caller's fd
3208 * or directory if supplied.
Nandana Dutt979388e2018-11-30 16:48:55 +00003209 */
Nandana Duttd2f5f082019-01-18 17:13:52 +00003210Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
3211 const std::string& calling_package) {
Rhed Jao5377d792020-07-16 17:37:39 +08003212 DurationReporter duration_reporter("RUN INTERNAL", /* logcat_only = */true);
Nandana Dutt979388e2018-11-30 16:48:55 +00003213 LogDumpOptions(*options_);
Nandana Dutt197661d2018-11-16 16:40:21 +00003214 if (!options_->ValidateOptions()) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00003215 MYLOGE("Invalid options specified\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003216 return RunStatus::INVALID_INPUT;
3217 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003218 /* set as high priority, and protect from OOM killer */
3219 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003220
Felipe Lemed071c682016-10-20 16:48:00 -07003221 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07003222 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003223 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003224 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003225 } else {
3226 /* fallback to kernels <= 2.6.35 */
3227 oom_adj = fopen("/proc/self/oom_adj", "we");
3228 if (oom_adj) {
3229 fputs("-17", oom_adj);
3230 fclose(oom_adj);
3231 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003232 }
3233
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003234 if (version_ == VERSION_DEFAULT) {
3235 version_ = VERSION_CURRENT;
Michal Karpinski4db754f2015-12-11 18:04:32 +00003236 }
3237
Chris Morin5a50d482022-02-01 17:41:18 -08003238 if (version_ != VERSION_CURRENT) {
3239 MYLOGE("invalid version requested ('%s'); supported values are: ('%s', '%s')\n",
3240 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003241 return RunStatus::INVALID_INPUT;
Felipe Lemed071c682016-10-20 16:48:00 -07003242 }
3243
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003244 if (options_->show_header_only) {
3245 PrintHeader();
3246 return RunStatus::OK;
Felipe Lemed071c682016-10-20 16:48:00 -07003247 }
3248
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003249 MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n",
3250 calling_uid, calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003251
Felipe Leme7447d7c2016-11-03 18:12:22 -07003252 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003253 std::string stats_path =
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003254 android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003255 progress_.reset(new Progress(stats_path));
Felipe Leme7447d7c2016-11-03 18:12:22 -07003256
Sahana Raof35ed432019-07-12 10:47:52 +01003257 if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
3258 MYLOGE("Failed to acquire wake lock: %s\n", strerror(errno));
3259 } else {
3260 // Wake lock will be released automatically on process death
3261 MYLOGD("Wake lock acquired.\n");
3262 }
3263
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08003264 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07003265
Felipe Lemef0292972016-11-22 13:57:05 -08003266 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07003267 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
3268 }
3269
Kevin Jeonfa64e642023-07-27 11:36:41 -04003270 if (PropertiesHelper::IsStrictRun()) {
3271 MYLOGI(
3272 "Running on strict-run mode, which has shorter timeouts "
3273 "(to disable, call 'setprop dumpstate.strict_run false')\n");
3274 }
3275
Nandana Dutt235c6672019-11-14 15:22:32 +00003276 MYLOGI("dumpstate info: id=%d, args='%s', bugreport_mode= %s bugreport format version: %s\n",
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00003277 id_, options_->args.c_str(), options_->bugreport_mode_string.c_str(), version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08003278
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003279 do_early_screenshot_ = options_->do_progress_updates;
Felipe Lemee338bf62015-12-07 14:03:50 -08003280
Christopher Ferrised9354f2014-10-01 17:35:01 -07003281 // If we are going to use a socket, do it as early as possible
3282 // to avoid timeouts from bugreport.
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003283 if (options_->stream_to_socket || options_->progress_updates_to_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07003284 MYLOGD("Opening control socket\n");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003285 control_socket_fd_ = open_socket_fn_("dumpstate");
Nandana Dutta344cb62019-02-22 15:12:35 +00003286 if (control_socket_fd_ == -1) {
3287 return ERROR;
3288 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003289 if (options_->progress_updates_to_socket) {
3290 options_->do_progress_updates = 1;
3291 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07003292 }
3293
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003294 if (!PrepareToWriteToFile()) {
3295 return ERROR;
3296 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08003297
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003298 // Interactive, wear & telephony modes are default to true.
3299 // and may enable from cli option or when using control socket
3300 if (options_->do_progress_updates) {
3301 // clang-format off
3302 std::vector<std::string> am_args = {
3303 "--receiver-permission", "android.permission.DUMP",
3304 };
3305 // clang-format on
3306 // Send STARTED broadcast for apps that listen to bugreport generation events
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003307 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED",
3308 am_args, multiuser_get_user_id(calling_uid));
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003309 if (options_->progress_updates_to_socket) {
3310 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08003311 }
3312 }
3313
Nick Kralevichf3599b32016-01-25 15:05:16 -08003314 /* read /proc/cmdline before dropping root */
3315 FILE *cmdline = fopen("/proc/cmdline", "re");
3316 if (cmdline) {
3317 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
3318 fclose(cmdline);
3319 }
3320
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003321 if (options_->do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08003322 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05003323 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003324
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003325 if (zip_file != nullptr) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003326 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
3327 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003328 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08003329 }
3330 }
3331
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003332 int dup_stdout_fd;
3333 int dup_stderr_fd;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003334 // Redirect stderr to log_path_ for debugging.
3335 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
3336 if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
3337 return ERROR;
3338 }
3339 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
3340 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
3341 strerror(errno));
3342 }
Nandana Dutt979388e2018-11-30 16:48:55 +00003343
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003344 // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
3345 // moved into zip file later, if zipping.
3346 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
3347 // TODO: why not write to a file instead of stdout to overcome this problem?
3348 /* TODO: rather than generating a text file now and zipping it later,
3349 it would be more efficient to redirect stdout to the zip entry
3350 directly, but the libziparchive doesn't support that option yet. */
3351 if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
3352 return ERROR;
3353 }
3354 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
3355 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
3356 tmp_path_.c_str(), strerror(errno));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003357 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08003358
3359 // Don't buffer stdout
3360 setvbuf(stdout, nullptr, _IONBF, 0);
3361
Rhed Jao5377d792020-07-16 17:37:39 +08003362 // Enable the parallel run if the client requests to output to a file.
3363 EnableParallelRunIfNeeded();
3364 // Using scope guard to make sure the dump pool can be shut down correctly.
3365 auto scope_guard_to_shutdown_pool = android::base::make_scope_guard([=]() {
3366 ShutdownDumpPool();
3367 });
3368
Felipe Leme608385d2016-02-01 10:35:38 -08003369 // NOTE: there should be no stdout output until now, otherwise it would break the header.
3370 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08003371 // duration is logged into MYLOG instead.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003372 PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003373
Kean Mariottic14cebc2024-03-04 10:55:28 +00003374 bool system_trace_exists = access(SYSTEM_TRACE_SNAPSHOT, F_OK) == 0;
3375 if (options_->use_predumped_ui_data && !system_trace_exists) {
3376 MYLOGW("Ignoring 'use predumped data' flag because no predumped data is available");
3377 options_->use_predumped_ui_data = false;
3378 }
3379
Kean Mariottica20f2d2023-12-15 09:34:25 +00003380 std::future<std::string> snapshot_system_trace;
3381
Kean Mariotti853b73a2023-07-27 12:40:30 +00003382 bool is_dumpstate_restricted =
3383 options_->telephony_only || options_->wifi_only || options_->limited_only;
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003384 if (!is_dumpstate_restricted) {
3385 // Snapshot the system trace now (if running) to avoid that dumpstate's
3386 // own activity pushes out interesting data from the trace ring buffer.
3387 // The trace file is added to the zip by MaybeAddSystemTraceToZip().
Kean Mariottica20f2d2023-12-15 09:34:25 +00003388 snapshot_system_trace = MaybeSnapshotSystemTraceAsync();
Yohei Yukawa95305b32021-03-09 07:54:27 -08003389
Kean Mariotti853b73a2023-07-27 12:40:30 +00003390 // Invoke critical dumpsys to preserve system state, before doing anything else.
3391 RunDumpsysCritical();
3392
Kean Mariotti306633e2022-09-05 16:30:47 +00003393 // Snapshot the UI traces now (if running).
3394 // The trace files will be added to bugreport later.
3395 MaybeSnapshotUiTraces();
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003396 }
Kean Mariotti853b73a2023-07-27 12:40:30 +00003397
3398 MaybeTakeEarlyScreenshot();
Kean Mariottica20f2d2023-12-15 09:34:25 +00003399 MaybeWaitForSnapshotSystemTrace(std::move(snapshot_system_trace));
Gavin Corkery6968f552020-11-22 18:09:05 +00003400 onUiIntensiveBugreportDumpsFinished(calling_uid);
3401 MaybeCheckUserConsent(calling_uid, calling_package);
3402 if (options_->telephony_only) {
3403 DumpstateTelephonyOnly(calling_package);
3404 } else if (options_->wifi_only) {
3405 DumpstateWifiOnly();
3406 } else if (options_->limited_only) {
3407 DumpstateLimitedOnly();
Elis Elliott8e401ad2023-08-08 11:18:59 +00003408 } else if (options_->onboarding_only) {
3409 DumpstateOnboardingOnly();
Gavin Corkery6968f552020-11-22 18:09:05 +00003410 } else {
Nandana Dutt4be45d12018-09-26 15:04:23 +01003411 // Dump state for the default case. This also drops root.
Jichao Lie89d9c12019-11-21 19:02:51 -08003412 RunStatus s = DumpstateDefaultAfterCritical();
Nandana Dutt5c390032019-03-12 10:52:56 +00003413 if (s != RunStatus::OK) {
Nandana Duttaac6f582019-07-26 14:32:47 +01003414 if (s == RunStatus::USER_CONSENT_DENIED) {
Nandana Dutt5c390032019-03-12 10:52:56 +00003415 HandleUserConsentDenied();
3416 }
3417 return s;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08003418 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07003419 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07003420
Felipe Leme55b42a62015-11-10 17:39:08 -08003421 /* close output if needed */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003422 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003423
Abhijeet Kaure370d682019-10-01 16:49:30 +01003424 // Zip the (now complete) .tmp file within the internal directory.
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003425 ATRACE_BEGIN("FinalizeFile");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003426 FinalizeFile();
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003427 ATRACE_END();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003428
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003429 // Share the final file with the caller if the user has consented or Shell is the caller.
Nandana Duttd2f5f082019-01-18 17:13:52 +00003430 Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
Gavin Corkerya44686c2022-11-23 18:16:51 +00003431 if (CalledByApi() && !options_->is_consent_deferred) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003432 status = CopyBugreportIfUserConsented(calling_uid);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003433 if (status != Dumpstate::RunStatus::OK &&
3434 status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3435 // Do an early return if there were errors. We make an exception for consent
3436 // timing out because it's possible the user got distracted. In this case the
3437 // bugreport is not shared but made available for manual retrieval.
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003438 MYLOGI("User denied consent. Returning\n");
Nandana Duttd2f5f082019-01-18 17:13:52 +00003439 return status;
3440 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003441 if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3442 MYLOGI(
3443 "Did not receive user consent yet."
3444 " Will not copy the bugreport artifacts to caller.\n");
Abhijeet Kaur57627412019-04-17 16:00:09 +01003445 const String16 incidentcompanion("incidentcompanion");
3446 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
3447 if (ics != nullptr) {
3448 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3449 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3450 consent_callback_.get());
3451 } else {
3452 MYLOGD("Unable to cancel user consent; incidentcompanion service unavailable\n");
3453 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003454 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003455 }
3456
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003457 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003458 if (options_->do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09003459 for (int i = 0; i < 3; i++) {
3460 Vibrate(75);
3461 usleep((75 + 50) * 1000);
3462 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003463 }
3464
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003465 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
3466 progress_->GetInitialMax());
3467 progress_->Save();
3468 MYLOGI("done (id %d)\n", id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003469
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003470 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08003471
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003472 if (control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07003473 MYLOGD("Closing control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003474 close(control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07003475 }
3476
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003477 tombstone_data_.clear();
3478 anr_data_.clear();
Andy Hungd62f7e62024-01-11 15:47:52 -08003479 anr_trace_data_.clear();
Woody Lin20767a92022-11-29 15:50:24 +08003480 shutdown_checkpoints_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01003481
Nandana Duttd2f5f082019-01-18 17:13:52 +00003482 return (consent_callback_ != nullptr &&
3483 consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
3484 ? USER_CONSENT_TIMED_OUT
3485 : RunStatus::OK;
3486}
3487
Paul Chang0d2aad72020-02-13 20:04:03 +08003488void Dumpstate::MaybeTakeEarlyScreenshot() {
3489 if (!options_->do_screenshot || !do_early_screenshot_) {
3490 return;
3491 }
3492
3493 TakeScreenshot();
3494}
3495
Kean Mariottica20f2d2023-12-15 09:34:25 +00003496std::future<std::string> Dumpstate::MaybeSnapshotSystemTraceAsync() {
Kean Mariotti853b73a2023-07-27 12:40:30 +00003497 // When capturing traces via bugreport handler (BH), this function will be invoked twice:
3498 // 1) When BH invokes IDumpstate::PreDumpUiData()
3499 // 2) When BH invokes IDumpstate::startBugreport(flags = BUGREPORT_USE_PREDUMPED_UI_DATA)
3500 // In this case we don't want to re-invoke perfetto in step 2.
3501 // In all other standard invocation states, this function is invoked once
3502 // without the flag BUGREPORT_USE_PREDUMPED_UI_DATA.
Kean Mariottica20f2d2023-12-15 09:34:25 +00003503 // This function must run asynchronously to avoid delaying MaybeTakeEarlyScreenshot() in the
3504 // standard invocation states (b/316110955).
Kean Mariotti853b73a2023-07-27 12:40:30 +00003505 if (options_->use_predumped_ui_data) {
Kean Mariottica20f2d2023-12-15 09:34:25 +00003506 return {};
3507 }
3508
3509 // Create temporary file for the command's output
3510 std::string outPath = ds.bugreport_internal_dir_ + "/tmp_serialize_perfetto_trace";
3511 auto outFd = android::base::unique_fd(TEMP_FAILURE_RETRY(
3512 open(outPath.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
3513 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
3514 if (outFd < 0) {
3515 MYLOGE("Could not open %s to serialize perfetto trace.\n", outPath.c_str());
3516 return {};
Kean Mariotti853b73a2023-07-27 12:40:30 +00003517 }
3518
3519 // If a stale file exists already, remove it.
3520 unlink(SYSTEM_TRACE_SNAPSHOT);
3521
Kean Mariottica20f2d2023-12-15 09:34:25 +00003522 MYLOGI("Launching async '%s'", SERIALIZE_PERFETTO_TRACE_TASK.c_str())
3523 return std::async(
3524 std::launch::async, [this, outPath = std::move(outPath), outFd = std::move(outFd)] {
3525 // If a background system trace is happening and is marked as "suitable for
3526 // bugreport" (i.e. bugreport_score > 0 in the trace config), this command
3527 // will stop it and serialize into SYSTEM_TRACE_SNAPSHOT. In the (likely)
3528 // case that no trace is ongoing, this command is a no-op.
3529 // Note: this should not be enqueued as we need to freeze the trace before
3530 // dumpstate starts. Otherwise the trace ring buffers will contain mostly
3531 // the dumpstate's own activity which is irrelevant.
3532 RunCommand(
3533 SERIALIZE_PERFETTO_TRACE_TASK, {"perfetto", "--save-for-bugreport"},
3534 CommandOptions::WithTimeout(10).DropRoot().CloseAllFileDescriptorsOnExec().Build(),
3535 false, outFd);
3536 // MaybeAddSystemTraceToZip() will take care of copying the trace in the zip
3537 // file in the later stages.
3538
3539 return outPath;
3540 });
3541}
3542
3543void Dumpstate::MaybeWaitForSnapshotSystemTrace(std::future<std::string> task) {
3544 if (!task.valid()) {
3545 return;
3546 }
3547
3548 WaitForTask(std::move(task), SERIALIZE_PERFETTO_TRACE_TASK, STDOUT_FILENO);
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003549}
3550
Kean Mariotti306633e2022-09-05 16:30:47 +00003551void Dumpstate::MaybeSnapshotUiTraces() {
3552 if (PropertiesHelper::IsUserBuild() || options_->use_predumped_ui_data) {
3553 return;
3554 }
3555
Pablo Gamito654831c2024-02-16 16:47:48 +00003556 std::vector<std::vector<std::string>> dumpTracesForBugReportCommands = {
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003557 {"cmd", "input_method", "tracing", "save-for-bugreport"},
3558 {"cmd", "window", "tracing", "save-for-bugreport"},
3559 {"cmd", "window", "shell", "tracing", "save-for-bugreport"},
3560 };
Hongwei Wang39229132023-01-24 15:09:59 -08003561
Pablo Gamito654831c2024-02-16 16:47:48 +00003562 if (!android_tracing_perfetto_transition_tracing()) {
3563 dumpTracesForBugReportCommands.push_back({"dumpsys", "activity", "service",
3564 "SystemUIService", "WMShell", "transitions",
3565 "tracing", "save-for-bugreport"});
3566 }
3567
Pablo Gamito6929a0e2024-02-26 23:29:47 +00003568 if (!android_tracing_perfetto_protolog_tracing()) {
Pablo Gamito654831c2024-02-16 16:47:48 +00003569 dumpTracesForBugReportCommands.push_back({"dumpsys", "activity", "service",
3570 "SystemUIService", "WMShell", "protolog",
3571 "save-for-bugreport"});
3572 }
3573
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003574 for (const auto& command : dumpTracesForBugReportCommands) {
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003575 RunCommand(
3576 // Empty name because it's not intended to be classified as a bugreport section.
3577 // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003578 "", command,
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003579 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
3580 }
Kean Mariotti306633e2022-09-05 16:30:47 +00003581}
3582
3583void Dumpstate::MaybeAddUiTracesToZip() {
3584 if (PropertiesHelper::IsUserBuild()) {
3585 return;
3586 }
3587
3588 ds.AddDir(WMTRACE_DATA_DIR, false);
Yohei Yukawa95305b32021-03-09 07:54:27 -08003589}
3590
Paul Changeb4b4642020-05-28 22:05:47 +08003591void Dumpstate::onUiIntensiveBugreportDumpsFinished(int32_t calling_uid) {
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003592 if (multiuser_get_app_id(calling_uid) == AID_SHELL || !CalledByApi()) {
Paul Changc490e662020-04-11 18:14:09 +08003593 return;
3594 }
3595 if (listener_ != nullptr) {
3596 // Let listener know ui intensive bugreport dumps are finished, then it can do event
3597 // handling if required.
Paul Changeb4b4642020-05-28 22:05:47 +08003598 listener_->onUiIntensiveBugreportDumpsFinished();
Paul Changc490e662020-04-11 18:14:09 +08003599 }
3600}
3601
Jichao Lie89d9c12019-11-21 19:02:51 -08003602void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) {
Gavin Corkerya44686c2022-11-23 18:16:51 +00003603 if (multiuser_get_app_id(calling_uid) == AID_SHELL ||
Kholoud Mohameddef4e432024-05-15 12:47:46 +00003604 !CalledByApi() || options_->is_consent_deferred ||
3605 (android::app::admin::flags::onboarding_consentless_bugreports() &&
3606 options_->skip_user_consent)) {
Gavin Corkerya44686c2022-11-23 18:16:51 +00003607 // No need to get consent for shell triggered dumpstates, or not
3608 // through bugreporting API (i.e. no fd to copy back), or when consent
3609 // is deferred.
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003610 return;
3611 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003612 consent_callback_ = new ConsentCallback();
3613 const String16 incidentcompanion("incidentcompanion");
3614 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
Jichao Lie89d9c12019-11-21 19:02:51 -08003615 android::String16 package(calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003616 if (ics != nullptr) {
3617 MYLOGD("Checking user consent via incidentcompanion service\n");
Steven Leeb573eb82022-11-29 22:31:35 +08003618 int flags = 0x1; // IncidentManager.FLAG_CONFIRMATION_DIALOG
3619 if (IsConsentlessBugreportAllowed(*options_)) {
3620 flags |= 0x2; // IncidentManager.FLAG_ALLOW_CONSENTLESS_BUGREPORT
3621 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003622 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
Steven Leeb573eb82022-11-29 22:31:35 +08003623 calling_uid, package, String16(), String16(), flags, consent_callback_.get());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003624 } else {
3625 MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
3626 }
3627}
3628
Nandana Dutt5c390032019-03-12 10:52:56 +00003629bool Dumpstate::IsUserConsentDenied() const {
3630 return ds.consent_callback_ != nullptr &&
3631 ds.consent_callback_->getResult() == UserConsentResult::DENIED;
3632}
3633
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01003634bool Dumpstate::CalledByApi() const {
3635 return ds.options_->bugreport_fd.get() != -1 ? true : false;
3636}
3637
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003638void Dumpstate::CleanupTmpFiles() {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003639 android::os::UnlinkAndLogOnError(tmp_path_);
3640 android::os::UnlinkAndLogOnError(screenshot_path_);
3641 android::os::UnlinkAndLogOnError(path_);
Gavin Corkery789d7a52021-02-24 23:52:35 +00003642 if (dump_traces_path != nullptr) {
3643 android::os::UnlinkAndLogOnError(dump_traces_path);
3644 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003645}
3646
Rhed Jao5377d792020-07-16 17:37:39 +08003647void Dumpstate::EnableParallelRunIfNeeded() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003648 if (!PropertiesHelper::IsParallelRun()) {
Rhed Jao5377d792020-07-16 17:37:39 +08003649 return;
3650 }
3651 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003652 zip_entry_tasks_ = std::make_unique<TaskQueue>();
Rhed Jao5377d792020-07-16 17:37:39 +08003653}
3654
3655void Dumpstate::ShutdownDumpPool() {
3656 if (dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08003657 dump_pool_.reset();
Rhed Jao5377d792020-07-16 17:37:39 +08003658 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003659 if (zip_entry_tasks_) {
3660 zip_entry_tasks_->run(/* do_cancel = */true);
3661 zip_entry_tasks_ = nullptr;
3662 }
3663}
3664
3665void Dumpstate::EnqueueAddZipEntryAndCleanupIfNeeded(const std::string& entry_name,
3666 const std::string& entry_path) {
3667 auto func_add_zip_entry_and_cleanup = [=](bool task_cancelled) {
3668 if (!task_cancelled) {
3669 AddZipEntry(entry_name, entry_path);
3670 }
3671 android::os::UnlinkAndLogOnError(entry_path);
3672 };
3673 if (zip_entry_tasks_) {
3674 // Enqueues AddZipEntryAndCleanup function if the parallel run is enabled.
3675 zip_entry_tasks_->add(func_add_zip_entry_and_cleanup, _1);
3676 } else {
3677 // Invokes AddZipEntryAndCleanup immediately
3678 std::invoke(func_add_zip_entry_and_cleanup, /* task_cancelled = */false);
3679 }
Rhed Jao5377d792020-07-16 17:37:39 +08003680}
3681
Nandana Duttd2f5f082019-01-18 17:13:52 +00003682Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
3683 MYLOGD("User denied consent; deleting files and returning\n");
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003684 CleanupTmpFiles();
Nandana Duttd2f5f082019-01-18 17:13:52 +00003685 return USER_CONSENT_DENIED;
3686}
3687
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003688Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented(int32_t calling_uid) {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003689 // If the caller has asked to copy the bugreport over to their directory, we need explicit
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003690 // user consent (unless the caller is Shell).
3691 UserConsentResult consent_result;
Kholoud Mohameddef4e432024-05-15 12:47:46 +00003692 if (multiuser_get_app_id(calling_uid) == AID_SHELL || (options_->skip_user_consent
3693 && android::app::admin::flags::onboarding_consentless_bugreports())) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003694 consent_result = UserConsentResult::APPROVED;
3695 } else {
3696 consent_result = consent_callback_->getResult();
3697 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003698 if (consent_result == UserConsentResult::UNAVAILABLE) {
3699 // User has not responded yet.
3700 uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
Hunter Knepshield70610fa2020-01-03 15:27:33 -08003701 // Telephony is a fast report type, particularly on user builds where information may be
3702 // more aggressively limited. To give the user time to read the consent dialog, increase the
3703 // timeout.
3704 uint64_t timeout_ms = options_->telephony_only ? TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS
3705 : USER_CONSENT_TIMEOUT_MS;
3706 if (elapsed_ms < timeout_ms) {
3707 uint delay_seconds = (timeout_ms - elapsed_ms) / 1000;
Nandana Duttd2f5f082019-01-18 17:13:52 +00003708 MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
3709 sleep(delay_seconds);
3710 }
3711 consent_result = consent_callback_->getResult();
3712 }
3713 if (consent_result == UserConsentResult::DENIED) {
3714 // User has explicitly denied sharing with the app. To be safe delete the
3715 // internal bugreport & tmp files.
3716 return HandleUserConsentDenied();
3717 }
3718 if (consent_result == UserConsentResult::APPROVED) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00003719 bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
3720 if (copy_succeeded) {
3721 android::os::UnlinkAndLogOnError(path_);
Abhijeet Kaur9ce94672020-04-01 17:22:36 +01003722 if (options_->do_screenshot &&
3723 options_->screenshot_fd.get() != -1 &&
3724 !options_->is_screenshot_copied) {
3725 copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
3726 options_->screenshot_fd.get());
3727 options_->is_screenshot_copied = copy_succeeded;
3728 if (copy_succeeded) {
3729 android::os::UnlinkAndLogOnError(screenshot_path_);
3730 }
3731 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003732 }
3733 return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
3734 } else if (consent_result == UserConsentResult::UNAVAILABLE) {
3735 // consent_result is still UNAVAILABLE. The user has likely not responded yet.
3736 // Since we do not have user consent to share the bugreport it does not get
3737 // copied over to the calling app but remains in the internal directory from
3738 // where the user can manually pull it.
Paul Changce644212021-05-11 16:06:45 +08003739 std::string final_path = GetPath(".zip");
3740 bool copy_succeeded = android::os::CopyFileToFile(path_, final_path);
3741 if (copy_succeeded) {
3742 android::os::UnlinkAndLogOnError(path_);
3743 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003744 return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
3745 }
3746 // Unknown result; must be a programming error.
3747 MYLOGE("Unknown user consent result:%d\n", consent_result);
3748 return Dumpstate::RunStatus::ERROR;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003749}
3750
Nandana Duttf02564e2019-02-15 15:24:24 +00003751Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003752 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
3753 Dumpstate::RunStatus status = options->Initialize(argc, argv);
3754 if (status == Dumpstate::RunStatus::OK) {
Nandana Duttf02564e2019-02-15 15:24:24 +00003755 SetOptions(std::move(options));
Nandana Duttd2f5f082019-01-18 17:13:52 +00003756 // When directly running dumpstate binary, the output is not expected to be written
3757 // to any external file descriptor.
Nandana Duttf02564e2019-02-15 15:24:24 +00003758 assert(options_->bugreport_fd.get() == -1);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003759
3760 // calling_uid and calling_package are for user consent to share the bugreport with
Abhijeet Kaura407fb82020-03-27 12:51:12 +00003761 // an app; they are irrelevant here because bugreport is triggered via command line.
3762 // Update Last ID before calling Run().
3763 Initialize();
Nikhil Kumarb70622a2023-06-15 15:37:19 +01003764 status = Run(0 /* calling_uid */, "" /* calling_package */);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003765 }
Nandana Duttf02564e2019-02-15 15:24:24 +00003766 return status;
3767}
3768
3769/* Main entry point for dumpstate binary. */
3770int run_main(int argc, char* argv[]) {
3771 Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003772
3773 switch (status) {
3774 case Dumpstate::RunStatus::OK:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003775 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003776 case Dumpstate::RunStatus::HELP:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003777 ShowUsage();
3778 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003779 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003780 fprintf(stderr, "Invalid combination of args\n");
3781 ShowUsage();
3782 exit(1);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003783 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003784 FALLTHROUGH_INTENDED;
3785 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3786 FALLTHROUGH_INTENDED;
3787 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003788 exit(2);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003789 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003790}
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003791
3792// TODO(111441001): Default DumpOptions to sensible values.
3793Dumpstate::Dumpstate(const std::string& version)
3794 : pid_(getpid()),
3795 options_(new Dumpstate::DumpOptions()),
Nandana Dutt402a8392019-06-14 14:25:13 +01003796 last_reported_percent_progress_(0),
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003797 version_(version),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003798 now_(time(nullptr)),
3799 open_socket_fn_(open_socket) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003800}
3801
3802Dumpstate& Dumpstate::GetInstance() {
3803 static Dumpstate singleton_(android::base::GetProperty("dumpstate.version", VERSION_CURRENT));
3804 return singleton_;
3805}
3806
Rhed Jao5377d792020-07-16 17:37:39 +08003807DurationReporter::DurationReporter(const std::string& title, bool logcat_only, bool verbose,
3808 int duration_fd) : title_(title), logcat_only_(logcat_only), verbose_(verbose),
3809 duration_fd_(duration_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003810 if (!title_.empty()) {
3811 started_ = Nanotime();
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003812 if (title_.find("SHOW MAP") == std::string::npos) {
3813 ATRACE_ASYNC_BEGIN(title_.c_str(), 0);
3814 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003815 }
3816}
3817
3818DurationReporter::~DurationReporter() {
3819 if (!title_.empty()) {
3820 float elapsed = (float)(Nanotime() - started_) / NANOS_PER_SEC;
chenqiwuaf8b2d92019-12-12 18:53:51 +08003821 if (elapsed >= .5f || verbose_) {
3822 MYLOGD("Duration of '%s': %.2fs\n", title_.c_str(), elapsed);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003823 }
chenqiwuaf8b2d92019-12-12 18:53:51 +08003824 if (!logcat_only_) {
3825 // Use "Yoda grammar" to make it easier to grep|sort sections.
Rhed Jao5377d792020-07-16 17:37:39 +08003826 dprintf(duration_fd_, "------ %.3fs was the duration of '%s' ------\n",
3827 elapsed, title_.c_str());
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003828 }
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003829 if (title_.find("SHOW MAP") == std::string::npos) {
3830 ATRACE_ASYNC_END(title_.c_str(), 0);
3831 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003832 }
3833}
3834
3835const int32_t Progress::kDefaultMax = 5000;
3836
3837Progress::Progress(const std::string& path) : Progress(Progress::kDefaultMax, 1.1, path) {
3838}
3839
3840Progress::Progress(int32_t initial_max, int32_t progress, float growth_factor)
3841 : Progress(initial_max, growth_factor, "") {
3842 progress_ = progress;
3843}
3844
3845Progress::Progress(int32_t initial_max, float growth_factor, const std::string& path)
3846 : initial_max_(initial_max),
3847 progress_(0),
3848 max_(initial_max),
3849 growth_factor_(growth_factor),
3850 n_runs_(0),
3851 average_max_(0),
3852 path_(path) {
3853 if (!path_.empty()) {
3854 Load();
3855 }
3856}
3857
3858void Progress::Load() {
3859 MYLOGD("Loading stats from %s\n", path_.c_str());
3860 std::string content;
3861 if (!android::base::ReadFileToString(path_, &content)) {
3862 MYLOGI("Could not read stats from %s; using max of %d\n", path_.c_str(), max_);
3863 return;
3864 }
3865 if (content.empty()) {
3866 MYLOGE("No stats (empty file) on %s; using max of %d\n", path_.c_str(), max_);
3867 return;
3868 }
3869 std::vector<std::string> lines = android::base::Split(content, "\n");
3870
3871 if (lines.size() < 1) {
3872 MYLOGE("Invalid stats on file %s: not enough lines (%d). Using max of %d\n", path_.c_str(),
3873 (int)lines.size(), max_);
3874 return;
3875 }
3876 char* ptr;
3877 n_runs_ = strtol(lines[0].c_str(), &ptr, 10);
3878 average_max_ = strtol(ptr, nullptr, 10);
3879 if (n_runs_ <= 0 || average_max_ <= 0 || n_runs_ > STATS_MAX_N_RUNS ||
3880 average_max_ > STATS_MAX_AVERAGE) {
3881 MYLOGE("Invalid stats line on file %s: %s\n", path_.c_str(), lines[0].c_str());
3882 initial_max_ = Progress::kDefaultMax;
3883 } else {
3884 initial_max_ = average_max_;
3885 }
3886 max_ = initial_max_;
3887
3888 MYLOGI("Average max progress: %d in %d runs; estimated max: %d\n", average_max_, n_runs_, max_);
3889}
3890
3891void Progress::Save() {
3892 int32_t total = n_runs_ * average_max_ + progress_;
3893 int32_t runs = n_runs_ + 1;
3894 int32_t average = floor(((float)total) / runs);
3895 MYLOGI("Saving stats (total=%d, runs=%d, average=%d) on %s\n", total, runs, average,
3896 path_.c_str());
3897 if (path_.empty()) {
3898 return;
3899 }
3900
3901 std::string content = android::base::StringPrintf("%d %d\n", runs, average);
3902 if (!android::base::WriteStringToFile(content, path_)) {
3903 MYLOGE("Could not save stats on %s\n", path_.c_str());
3904 }
3905}
3906
3907int32_t Progress::Get() const {
3908 return progress_;
3909}
3910
3911bool Progress::Inc(int32_t delta_sec) {
3912 bool changed = false;
3913 if (delta_sec >= 0) {
3914 progress_ += delta_sec;
3915 if (progress_ > max_) {
3916 int32_t old_max = max_;
3917 max_ = floor((float)progress_ * growth_factor_);
3918 MYLOGD("Adjusting max progress from %d to %d\n", old_max, max_);
3919 changed = true;
3920 }
3921 }
3922 return changed;
3923}
3924
3925int32_t Progress::GetMax() const {
3926 return max_;
3927}
3928
3929int32_t Progress::GetInitialMax() const {
3930 return initial_max_;
3931}
3932
3933void Progress::Dump(int fd, const std::string& prefix) const {
3934 const char* pr = prefix.c_str();
3935 dprintf(fd, "%sprogress: %d\n", pr, progress_);
3936 dprintf(fd, "%smax: %d\n", pr, max_);
3937 dprintf(fd, "%sinitial_max: %d\n", pr, initial_max_);
3938 dprintf(fd, "%sgrowth_factor: %0.2f\n", pr, growth_factor_);
3939 dprintf(fd, "%spath: %s\n", pr, path_.c_str());
3940 dprintf(fd, "%sn_runs: %d\n", pr, n_runs_);
3941 dprintf(fd, "%saverage_max: %d\n", pr, average_max_);
3942}
3943
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003944std::string Dumpstate::GetPath(const std::string& suffix) const {
3945 return GetPath(bugreport_internal_dir_, suffix);
3946}
3947
3948std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
3949 return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
3950 name_.c_str(), suffix.c_str());
3951}
3952
3953void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
3954 progress_ = std::move(progress);
3955}
3956
3957void for_each_userid(void (*func)(int), const char *header) {
3958 std::string title = header == nullptr ? "for_each_userid" : android::base::StringPrintf(
3959 "for_each_userid(%s)", header);
3960 DurationReporter duration_reporter(title);
3961 if (PropertiesHelper::IsDryRun()) return;
3962
3963 DIR *d;
3964 struct dirent *de;
3965
3966 if (header) printf("\n------ %s ------\n", header);
3967 func(0);
3968
3969 if (!(d = opendir("/data/system/users"))) {
3970 printf("Failed to open /data/system/users (%s)\n", strerror(errno));
3971 return;
3972 }
3973
3974 while ((de = readdir(d))) {
3975 int userid;
3976 if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
3977 continue;
3978 }
3979 func(userid);
3980 }
3981
3982 closedir(d);
3983}
3984
3985static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
3986 DIR *d;
3987 struct dirent *de;
3988
3989 if (!(d = opendir("/proc"))) {
3990 printf("Failed to open /proc (%s)\n", strerror(errno));
3991 return;
3992 }
3993
3994 if (header) printf("\n------ %s ------\n", header);
3995 while ((de = readdir(d))) {
3996 if (ds.IsUserConsentDenied()) {
3997 MYLOGE(
3998 "Returning early because user denied consent to share bugreport with calling app.");
3999 closedir(d);
4000 return;
4001 }
4002 int pid;
4003 int fd;
4004 char cmdpath[255];
4005 char cmdline[255];
4006
4007 if (!(pid = atoi(de->d_name))) {
4008 continue;
4009 }
4010
4011 memset(cmdline, 0, sizeof(cmdline));
4012
4013 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
4014 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
4015 TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
4016 close(fd);
4017 if (cmdline[0]) {
4018 helper(pid, cmdline, arg);
4019 continue;
4020 }
4021 }
4022
4023 // if no cmdline, a kernel thread has comm
4024 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
4025 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
4026 TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
4027 close(fd);
4028 if (cmdline[1]) {
4029 cmdline[0] = '[';
4030 size_t len = strcspn(cmdline, "\f\b\r\n");
4031 cmdline[len] = ']';
4032 cmdline[len+1] = '\0';
4033 }
4034 }
4035 if (!cmdline[0]) {
4036 strcpy(cmdline, "N/A");
4037 }
4038 helper(pid, cmdline, arg);
4039 }
4040
4041 closedir(d);
4042}
4043
4044static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
4045 for_each_pid_func *func = (for_each_pid_func*) arg;
4046 func(pid, cmdline);
4047}
4048
4049void for_each_pid(for_each_pid_func func, const char *header) {
4050 std::string title = header == nullptr ? "for_each_pid"
4051 : android::base::StringPrintf("for_each_pid(%s)", header);
4052 DurationReporter duration_reporter(title);
4053 if (PropertiesHelper::IsDryRun()) return;
4054
4055 __for_each_pid(for_each_pid_helper, header, (void *) func);
4056}
4057
4058static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
4059 DIR *d;
4060 struct dirent *de;
4061 char taskpath[255];
4062 for_each_tid_func *func = (for_each_tid_func *) arg;
4063
4064 snprintf(taskpath, sizeof(taskpath), "/proc/%d/task", pid);
4065
4066 if (!(d = opendir(taskpath))) {
4067 printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
4068 return;
4069 }
4070
4071 func(pid, pid, cmdline);
4072
4073 while ((de = readdir(d))) {
4074 if (ds.IsUserConsentDenied()) {
4075 MYLOGE(
4076 "Returning early because user denied consent to share bugreport with calling app.");
4077 closedir(d);
4078 return;
4079 }
4080 int tid;
4081 int fd;
4082 char commpath[255];
4083 char comm[255];
4084
4085 if (!(tid = atoi(de->d_name))) {
4086 continue;
4087 }
4088
4089 if (tid == pid)
4090 continue;
4091
4092 snprintf(commpath, sizeof(commpath), "/proc/%d/comm", tid);
4093 memset(comm, 0, sizeof(comm));
4094 if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
4095 strcpy(comm, "N/A");
4096 } else {
4097 char *c;
4098 TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
4099 close(fd);
4100
4101 c = strrchr(comm, '\n');
4102 if (c) {
4103 *c = '\0';
4104 }
4105 }
4106 func(pid, tid, comm);
4107 }
4108
4109 closedir(d);
4110}
4111
4112void for_each_tid(for_each_tid_func func, const char *header) {
4113 std::string title = header == nullptr ? "for_each_tid"
4114 : android::base::StringPrintf("for_each_tid(%s)", header);
4115 DurationReporter duration_reporter(title);
4116
4117 if (PropertiesHelper::IsDryRun()) return;
4118
4119 __for_each_pid(for_each_tid_helper, header, (void *) func);
4120}
4121
4122void show_wchan(int pid, int tid, const char *name) {
4123 if (PropertiesHelper::IsDryRun()) return;
4124
4125 char path[255];
4126 char buffer[255];
4127 int fd, ret, save_errno;
4128 char name_buffer[255];
4129
4130 memset(buffer, 0, sizeof(buffer));
4131
4132 snprintf(path, sizeof(path), "/proc/%d/wchan", tid);
4133 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
4134 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
4135 return;
4136 }
4137
4138 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
4139 save_errno = errno;
4140 close(fd);
4141
4142 if (ret < 0) {
4143 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
4144 return;
4145 }
4146
4147 snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
4148 pid == tid ? 0 : 3, "", name);
4149
4150 printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
4151
4152 return;
4153}
4154
4155// print time in centiseconds
4156static void snprcent(char *buffer, size_t len, size_t spc,
4157 unsigned long long time) {
4158 static long hz; // cache discovered hz
4159
4160 if (hz <= 0) {
4161 hz = sysconf(_SC_CLK_TCK);
4162 if (hz <= 0) {
4163 hz = 1000;
4164 }
4165 }
4166
4167 // convert to centiseconds
4168 time = (time * 100 + (hz / 2)) / hz;
4169
4170 char str[16];
4171
4172 snprintf(str, sizeof(str), " %llu.%02u",
4173 time / 100, (unsigned)(time % 100));
4174 size_t offset = strlen(buffer);
4175 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
4176 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
4177}
4178
4179// print permille as a percent
4180static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
4181 char str[16];
4182
4183 snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
4184 size_t offset = strlen(buffer);
4185 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
4186 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
4187}
4188
4189void show_showtime(int pid, const char *name) {
4190 if (PropertiesHelper::IsDryRun()) return;
4191
4192 char path[255];
4193 char buffer[1023];
4194 int fd, ret, save_errno;
4195
4196 memset(buffer, 0, sizeof(buffer));
4197
4198 snprintf(path, sizeof(path), "/proc/%d/stat", pid);
4199 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
4200 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
4201 return;
4202 }
4203
4204 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
4205 save_errno = errno;
4206 close(fd);
4207
4208 if (ret < 0) {
4209 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
4210 return;
4211 }
4212
4213 // field 14 is utime
4214 // field 15 is stime
4215 // field 42 is iotime
4216 unsigned long long utime = 0, stime = 0, iotime = 0;
4217 if (sscanf(buffer,
4218 "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
4219 "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
4220 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
4221 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
4222 &utime, &stime, &iotime) != 3) {
4223 return;
4224 }
4225
4226 unsigned long long total = utime + stime;
4227 if (!total) {
4228 return;
4229 }
4230
4231 unsigned permille = (iotime * 1000 + (total / 2)) / total;
4232 if (permille > 1000) {
4233 permille = 1000;
4234 }
4235
4236 // try to beautify and stabilize columns at <80 characters
4237 snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
4238 if ((name[0] != '[') || utime) {
4239 snprcent(buffer, sizeof(buffer), 57, utime);
4240 }
4241 snprcent(buffer, sizeof(buffer), 65, stime);
4242 if ((name[0] != '[') || iotime) {
4243 snprcent(buffer, sizeof(buffer), 73, iotime);
4244 }
4245 if (iotime) {
4246 snprdec(buffer, sizeof(buffer), 79, permille);
4247 }
4248 puts(buffer); // adds a trailing newline
4249
4250 return;
4251}
4252
4253void do_dmesg() {
4254 const char *title = "KERNEL LOG (dmesg)";
4255 DurationReporter duration_reporter(title);
4256 printf("------ %s ------\n", title);
4257
4258 if (PropertiesHelper::IsDryRun()) return;
4259
4260 /* Get size of kernel buffer */
4261 int size = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
4262 if (size <= 0) {
4263 printf("Unexpected klogctl return value: %d\n\n", size);
4264 return;
4265 }
4266 char *buf = (char *) malloc(size + 1);
4267 if (buf == nullptr) {
4268 printf("memory allocation failed\n\n");
4269 return;
4270 }
4271 int retval = klogctl(KLOG_READ_ALL, buf, size);
4272 if (retval < 0) {
4273 printf("klogctl failure\n\n");
4274 free(buf);
4275 return;
4276 }
4277 buf[retval] = '\0';
4278 printf("%s\n\n", buf);
4279 free(buf);
4280 return;
4281}
4282
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004283int Dumpstate::DumpFile(const std::string& title, const std::string& path) {
4284 DurationReporter duration_reporter(title);
4285
4286 int status = DumpFileToFd(STDOUT_FILENO, title, path);
4287
4288 UpdateProgress(WEIGHT_FILE);
4289
4290 return status;
4291}
4292
4293int read_file_as_long(const char *path, long int *output) {
luoqiangwei15fcf2022024-03-07 15:29:20 +08004294 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
4295 if (fd.get() < 0) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004296 int err = errno;
4297 MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
4298 return -1;
4299 }
4300 char buffer[50];
luoqiangwei15fcf2022024-03-07 15:29:20 +08004301 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer, sizeof(buffer)));
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004302 if (bytes_read == -1) {
4303 MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
4304 return -2;
4305 }
4306 if (bytes_read == 0) {
4307 MYLOGE("File %s is empty\n", path);
4308 return -3;
4309 }
4310 *output = atoi(buffer);
4311 return 0;
4312}
4313
4314/* calls skip to gate calling dump_from_fd recursively
4315 * in the specified directory. dump_from_fd defaults to
4316 * dump_file_from_fd above when set to NULL. skip defaults
4317 * to false when set to NULL. dump_from_fd will always be
4318 * called with title NULL.
4319 */
4320int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
4321 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4322 DurationReporter duration_reporter(title);
4323 DIR *dirp;
4324 struct dirent *d;
4325 char *newpath = nullptr;
4326 const char *slash = "/";
4327 int retval = 0;
4328
4329 if (!title.empty()) {
4330 printf("------ %s (%s) ------\n", title.c_str(), dir);
4331 }
4332 if (PropertiesHelper::IsDryRun()) return 0;
4333
4334 if (dir[strlen(dir) - 1] == '/') {
4335 ++slash;
4336 }
4337 dirp = opendir(dir);
4338 if (dirp == nullptr) {
4339 retval = -errno;
4340 MYLOGE("%s: %s\n", dir, strerror(errno));
4341 return retval;
4342 }
4343
4344 if (!dump_from_fd) {
4345 dump_from_fd = dump_file_from_fd;
4346 }
4347 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4348 if ((d->d_name[0] == '.')
4349 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4350 || (d->d_name[1] == '\0'))) {
4351 continue;
4352 }
4353 asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
4354 (d->d_type == DT_DIR) ? "/" : "");
4355 if (!newpath) {
4356 retval = -errno;
4357 continue;
4358 }
4359 if (skip && (*skip)(newpath)) {
4360 continue;
4361 }
4362 if (d->d_type == DT_DIR) {
4363 int ret = dump_files("", newpath, skip, dump_from_fd);
4364 if (ret < 0) {
4365 retval = ret;
4366 }
4367 continue;
4368 }
4369 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
4370 if (fd.get() < 0) {
4371 retval = -1;
4372 printf("*** %s: %s\n", newpath, strerror(errno));
4373 continue;
4374 }
4375 (*dump_from_fd)(nullptr, newpath, fd.get());
4376 }
4377 closedir(dirp);
4378 if (!title.empty()) {
4379 printf("\n");
4380 }
4381 return retval;
4382}
4383
4384/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
4385 * it's possible to avoid issues where opening the file itself can get
4386 * stuck.
4387 */
4388int dump_file_from_fd(const char *title, const char *path, int fd) {
4389 if (PropertiesHelper::IsDryRun()) return 0;
4390
4391 int flags = fcntl(fd, F_GETFL);
4392 if (flags == -1) {
4393 printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
4394 return -1;
4395 } else if (!(flags & O_NONBLOCK)) {
4396 printf("*** %s: fd must have O_NONBLOCK set.\n", path);
4397 return -1;
4398 }
4399 return DumpFileFromFdToFd(title, path, fd, STDOUT_FILENO, PropertiesHelper::IsDryRun());
4400}
4401
4402int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004403 const CommandOptions& options, bool verbose_duration, int out_fd) {
4404 DurationReporter duration_reporter(title, false /* logcat_only */,
4405 verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004406
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004407 int status = RunCommandToFd(out_fd, title, full_command, options);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004408
4409 /* TODO: for now we're simplifying the progress calculation by using the
4410 * timeout as the weight. It's a good approximation for most cases, except when calling dumpsys,
4411 * where its weight should be much higher proportionally to its timeout.
4412 * Ideally, it should use a options.EstimatedDuration() instead...*/
4413 UpdateProgress(options.Timeout());
4414
4415 return status;
4416}
4417
4418void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
Rhed Jaoe017f982020-07-21 17:58:41 +08004419 const CommandOptions& options, long dumpsysTimeoutMs, int out_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004420 long timeout_ms = dumpsysTimeoutMs > 0 ? dumpsysTimeoutMs : options.TimeoutInMs();
4421 std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-T", std::to_string(timeout_ms)};
4422 dumpsys.insert(dumpsys.end(), dumpsys_args.begin(), dumpsys_args.end());
Rhed Jaoe017f982020-07-21 17:58:41 +08004423 RunCommand(title, dumpsys, options, false, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004424}
4425
Dieter Hsu105ad0c2020-09-29 15:23:33 +08004426static int open_socket(const char* service) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004427 int s = android_get_control_socket(service);
4428 if (s < 0) {
4429 MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
4430 return -1;
4431 }
4432 fcntl(s, F_SETFD, FD_CLOEXEC);
4433
4434 // Set backlog to 0 to make sure that queue size will be minimum.
4435 // In Linux, because the minimum queue will be 1, connect() will be blocked
4436 // if the other clients already called connect() and the connection request was not accepted.
4437 if (listen(s, 0) < 0) {
4438 MYLOGE("listen(control socket): %s\n", strerror(errno));
4439 return -1;
4440 }
4441
4442 struct sockaddr addr;
4443 socklen_t alen = sizeof(addr);
Abhijeet Kaur2113cae2019-09-13 09:24:15 +01004444 int fd = accept4(s, &addr, &alen, SOCK_CLOEXEC);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004445
4446 // Close socket just after accept(), to make sure that connect() by client will get error
4447 // when the socket is used by the other services.
4448 // There is still a race condition possibility between accept and close, but there is no way
4449 // to close-on-accept atomically.
4450 // See detail; b/123306389#comment25
4451 close(s);
4452
4453 if (fd < 0) {
4454 MYLOGE("accept(control socket): %s\n", strerror(errno));
4455 return -1;
4456 }
4457
4458 return fd;
4459}
4460
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004461// TODO: should call is_valid_output_file and/or be merged into it.
4462void create_parent_dirs(const char *path) {
4463 char *chp = const_cast<char *> (path);
4464
4465 /* skip initial slash */
4466 if (chp[0] == '/')
4467 chp++;
4468
4469 /* create leading directories, if necessary */
4470 struct stat dir_stat;
4471 while (chp && chp[0]) {
4472 chp = strchr(chp, '/');
4473 if (chp) {
4474 *chp = 0;
4475 if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
4476 MYLOGI("Creating directory %s\n", path);
4477 if (mkdir(path, 0770)) { /* drwxrwx--- */
4478 MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
4479 } else if (chown(path, AID_SHELL, AID_SHELL)) {
4480 MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
4481 }
4482 }
4483 *chp++ = '/';
4484 }
4485 }
4486}
4487
4488bool _redirect_to_file(FILE* redirect, char* path, int truncate_flag) {
4489 create_parent_dirs(path);
4490
4491 int fd = TEMP_FAILURE_RETRY(open(path,
4492 O_WRONLY | O_CREAT | truncate_flag | O_CLOEXEC | O_NOFOLLOW,
4493 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
4494 if (fd < 0) {
4495 MYLOGE("%s: %s\n", path, strerror(errno));
4496 return false;
4497 }
4498
4499 TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
4500 close(fd);
4501 return true;
4502}
4503
4504bool redirect_to_file(FILE* redirect, char* path) {
4505 return _redirect_to_file(redirect, path, O_TRUNC);
4506}
4507
4508bool redirect_to_existing_file(FILE* redirect, char* path) {
4509 return _redirect_to_file(redirect, path, O_APPEND);
4510}
4511
4512void dump_route_tables() {
4513 DurationReporter duration_reporter("DUMP ROUTE TABLES");
4514 if (PropertiesHelper::IsDryRun()) return;
4515 const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
4516 ds.DumpFile("RT_TABLES", RT_TABLES_PATH);
4517 FILE* fp = fopen(RT_TABLES_PATH, "re");
4518 if (!fp) {
4519 printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
4520 return;
4521 }
4522 char table[16];
4523 // Each line has an integer (the table number), a space, and a string (the table name). We only
4524 // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
4525 // Add a fixed max limit so this doesn't go awry.
4526 for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
4527 RunCommand("ROUTE TABLE IPv4", {"ip", "-4", "route", "show", "table", table});
4528 RunCommand("ROUTE TABLE IPv6", {"ip", "-6", "route", "show", "table", table});
4529 }
4530 fclose(fp);
4531}
4532
Li Li830179f2022-01-04 12:53:29 -08004533void dump_frozen_cgroupfs(const char *dir, int level,
4534 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4535 DIR *dirp;
4536 struct dirent *d;
4537 char *newpath = nullptr;
4538
4539 dirp = opendir(dir);
4540 if (dirp == nullptr) {
4541 MYLOGE("%s: %s\n", dir, strerror(errno));
4542 return;
4543 }
4544
4545 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4546 if ((d->d_name[0] == '.')
4547 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4548 || (d->d_name[1] == '\0'))) {
4549 continue;
4550 }
4551 if (d->d_type == DT_DIR) {
4552 asprintf(&newpath, "%s/%s/", dir, d->d_name);
4553 if (!newpath) {
4554 continue;
4555 }
4556 if (level == 0 && !strncmp(d->d_name, "uid_", 4)) {
4557 dump_frozen_cgroupfs(newpath, 1, dump_from_fd);
4558 } else if (level == 1 && !strncmp(d->d_name, "pid_", 4)) {
4559 char *freezer = nullptr;
4560 asprintf(&freezer, "%s/%s", newpath, "cgroup.freeze");
4561 if (freezer) {
4562 FILE* fp = fopen(freezer, "r");
4563 if (fp != NULL) {
4564 int frozen;
4565 fscanf(fp, "%d", &frozen);
4566 if (frozen > 0) {
4567 dump_files("", newpath, skip_none, dump_from_fd);
4568 }
4569 fclose(fp);
4570 }
4571 free(freezer);
4572 }
4573 }
4574 }
4575 }
4576 closedir(dirp);
4577}
4578
4579void dump_frozen_cgroupfs() {
Li Li830179f2022-01-04 12:53:29 -08004580 MYLOGD("Adding frozen processes from %s\n", CGROUPFS_DIR);
4581 DurationReporter duration_reporter("FROZEN CGROUPFS");
4582 if (PropertiesHelper::IsDryRun()) return;
4583 dump_frozen_cgroupfs(CGROUPFS_DIR, 0, _add_file_from_fd);
4584}
4585
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004586void Dumpstate::UpdateProgress(int32_t delta_sec) {
4587 if (progress_ == nullptr) {
4588 MYLOGE("UpdateProgress: progress_ not set\n");
4589 return;
4590 }
Rhed Jaobf63d8a2020-07-21 15:42:55 +08004591 // This function updates progress related members of the dumpstate and reports
4592 // progress percentage to the bugreport client. Since it could be called by
4593 // different dump tasks at the same time if the parallel run is enabled, a
4594 // mutex lock is necessary here to synchronize the call.
4595 std::lock_guard<std::recursive_mutex> lock(mutex_);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004596
4597 // Always update progess so stats can be tuned...
Nandana Dutt402a8392019-06-14 14:25:13 +01004598 progress_->Inc(delta_sec);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004599
4600 // ...but only notifiy listeners when necessary.
4601 if (!options_->do_progress_updates) return;
4602
4603 int progress = progress_->Get();
4604 int max = progress_->GetMax();
Nandana Dutt402a8392019-06-14 14:25:13 +01004605 int percent = 100 * progress / max;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004606
Nandana Dutt402a8392019-06-14 14:25:13 +01004607 if (last_reported_percent_progress_ > 0 && percent <= last_reported_percent_progress_) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004608 return;
4609 }
Nandana Dutt402a8392019-06-14 14:25:13 +01004610 last_reported_percent_progress_ = percent;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004611
4612 if (control_socket_fd_ >= 0) {
4613 dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
4614 fsync(control_socket_fd_);
4615 }
4616
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004617 if (listener_ != nullptr) {
Nandana Dutt235c6672019-11-14 15:22:32 +00004618 if (percent % 10 == 0) {
4619 // We don't want to spam logcat, so only log multiples of 10.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004620 MYLOGD("Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004621 } else {
4622 // stderr is ignored on normal invocations, but useful when calling
4623 // /system/bin/dumpstate directly for debuggging.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004624 fprintf(stderr, "Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004625 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004626
4627 listener_->onProgress(percent);
4628 }
4629}
4630
4631void Dumpstate::TakeScreenshot(const std::string& path) {
4632 const std::string& real_path = path.empty() ? screenshot_path_ : path;
4633 int status =
4634 RunCommand("", {"/system/bin/screencap", "-p", real_path},
4635 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
4636 if (status == 0) {
4637 MYLOGD("Screenshot saved on %s\n", real_path.c_str());
4638 } else {
4639 MYLOGE("Failed to take screenshot on %s\n", real_path.c_str());
4640 }
Paul Chang0d2aad72020-02-13 20:04:03 +08004641 if (listener_ != nullptr) {
4642 // Show a visual indication to indicate screenshot is taken via
4643 // IDumpstateListener.onScreenshotTaken()
4644 listener_->onScreenshotTaken(status == 0);
4645 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004646}
4647
4648bool is_dir(const char* pathname) {
4649 struct stat info;
4650 if (stat(pathname, &info) == -1) {
4651 return false;
4652 }
4653 return S_ISDIR(info.st_mode);
4654}
4655
4656time_t get_mtime(int fd, time_t default_mtime) {
4657 struct stat info;
4658 if (fstat(fd, &info) == -1) {
4659 return default_mtime;
4660 }
4661 return info.st_mtime;
4662}