blob: bb0ffe650bdbe2f36e6ec95828ccf25081a24577 [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
Alessio Balsini9e332a72024-12-10 15:31:57 +00001260static void DumpKernelMemoryAllocations() {
1261 if (!access("/proc/allocinfo", F_OK)) {
1262 // Print the top 100 biggest memory allocations of at least one byte.
1263 // The output is sorted by size, descending.
1264 RunCommand("KERNEL MEMORY ALLOCATIONS",
1265 {"alloctop", "--once", "--sort", "s", "--min", "1", "--lines", "100"});
1266 }
1267}
1268
Nandana Dutt5c390032019-03-12 10:52:56 +00001269static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, int priority,
1270 std::chrono::milliseconds timeout,
1271 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001272 auto start = std::chrono::steady_clock::now();
Vishnu Naire97d6122018-01-18 13:58:56 -08001273 sp<android::IServiceManager> sm = defaultServiceManager();
1274 Dumpsys dumpsys(sm.get());
Vishnu Naire97d6122018-01-18 13:58:56 -08001275 Vector<String16> args;
1276 Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
Vishnu Naire97d6122018-01-18 13:58:56 -08001277 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1278 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001279 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001280 std::string path(title);
1281 path.append(" - ").append(String8(service).c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -08001282 size_t bytes_written = 0;
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001283 if (PropertiesHelper::IsDryRun()) {
1284 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1285 dumpsys.writeDumpFooter(STDOUT_FILENO, service, std::chrono::milliseconds(1));
1286 } else {
Devin Mooref492c1a2023-03-15 19:19:03 +00001287 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP | Dumpsys::TYPE_PID |
1288 Dumpsys::TYPE_CLIENTS | Dumpsys::TYPE_THREAD,
Devin Mooreae68df22023-02-24 20:59:51 +00001289 service, args);
1290 if (status == OK) {
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001291 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1292 std::chrono::duration<double> elapsed_seconds;
1293 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH &&
1294 service == String16("meminfo")) {
1295 // Use a longer timeout for meminfo, since 30s is not always enough.
1296 status = dumpsys.writeDump(STDOUT_FILENO, service, 60s,
1297 /* as_proto = */ false, elapsed_seconds,
1298 bytes_written);
1299 } else {
1300 status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
1301 /* as_proto = */ false, elapsed_seconds,
1302 bytes_written);
1303 }
1304 dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
1305 bool dump_complete = (status == OK);
1306 dumpsys.stopDumpThread(dump_complete);
Devin Moorecdfa4602023-03-16 20:49:39 +00001307 } else {
1308 MYLOGE("Failed to start dump thread for service: %s, status: %d",
1309 String8(service).c_str(), status);
Gavin Corkeryfac7e2b2021-07-08 22:39:02 +01001310 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001311 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001312
1313 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1314 std::chrono::steady_clock::now() - start);
1315 if (elapsed_duration > timeout) {
1316 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1317 elapsed_duration.count());
1318 break;
1319 }
1320 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001321 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001322}
1323
Vishnu Nair64afc022018-02-01 15:29:34 -08001324static void RunDumpsysText(const std::string& title, int priority,
1325 std::chrono::milliseconds timeout,
1326 std::chrono::milliseconds service_timeout) {
1327 DurationReporter duration_reporter(title);
1328 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1329 fsync(STDOUT_FILENO);
1330 RunDumpsysTextByPriority(title, priority, timeout, service_timeout);
1331}
1332
1333/* Dump all services registered with Normal or Default priority. */
Nandana Dutt5c390032019-03-12 10:52:56 +00001334static Dumpstate::RunStatus RunDumpsysTextNormalPriority(const std::string& title,
1335 std::chrono::milliseconds timeout,
1336 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001337 DurationReporter duration_reporter(title);
1338 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1339 fsync(STDOUT_FILENO);
1340 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout,
1341 service_timeout);
Nandana Dutt5c390032019-03-12 10:52:56 +00001342
1343 RETURN_IF_USER_DENIED_CONSENT();
1344
1345 return RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1346 service_timeout);
Vishnu Nair64afc022018-02-01 15:29:34 -08001347}
1348
Nandana Dutt5c390032019-03-12 10:52:56 +00001349static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priority,
1350 std::chrono::milliseconds timeout,
1351 std::chrono::milliseconds service_timeout) {
Vishnu Naire97d6122018-01-18 13:58:56 -08001352 sp<android::IServiceManager> sm = defaultServiceManager();
1353 Dumpsys dumpsys(sm.get());
1354 Vector<String16> args;
1355 Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
1356 DurationReporter duration_reporter(title);
1357
1358 auto start = std::chrono::steady_clock::now();
1359 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
1360 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001361 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001362 std::string path(kProtoPath);
1363 path.append(String8(service).c_str());
1364 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
1365 path.append("_CRITICAL");
1366 } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
1367 path.append("_HIGH");
1368 }
1369 path.append(kProtoExt);
Steven Morelandcbd69fc2021-07-20 20:45:43 +00001370 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP, service, args);
Vishnu Naire97d6122018-01-18 13:58:56 -08001371 if (status == OK) {
1372 status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
1373 bool dumpTerminated = (status == OK);
1374 dumpsys.stopDumpThread(dumpTerminated);
1375 }
1376 ZipWriter::FileEntry file_entry;
1377 ds.zip_writer_->GetLastEntry(&file_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -08001378
1379 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1380 std::chrono::steady_clock::now() - start);
1381 if (elapsed_duration > timeout) {
1382 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1383 elapsed_duration.count());
1384 break;
1385 }
1386 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001387 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001388}
1389
Nandana Dutta7db6342018-11-21 14:53:34 +00001390// Runs dumpsys on services that must dump first and will take less than 100ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001391static Dumpstate::RunStatus RunDumpsysCritical() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001392 RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1393 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Nandana Dutt5c390032019-03-12 10:52:56 +00001394
1395 RETURN_IF_USER_DENIED_CONSENT();
1396
1397 return RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1398 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Vishnu Nair780b1282017-10-10 13:57:24 -07001399}
1400
1401// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001402static Dumpstate::RunStatus RunDumpsysHigh() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001403 // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
1404 // high priority. Reduce timeout once they are able to dump in a shorter time or
1405 // moved to a parallel task.
1406 RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1407 /* timeout= */ 90s, /* service_timeout= */ 30s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001408
1409 RETURN_IF_USER_DENIED_CONSENT();
1410
1411 return RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1412 /* timeout= */ 5s, /* service_timeout= */ 1s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001413}
1414
1415// Runs dumpsys on services that must dump but can take up to 10s to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001416static Dumpstate::RunStatus RunDumpsysNormal() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001417 RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001418
1419 RETURN_IF_USER_DENIED_CONSENT();
1420
1421 return RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1422 /* timeout= */ 90s, /* service_timeout= */ 10s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001423}
1424
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001425/*
1426 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1427 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1428 * if it's not running in the parallel task.
1429 */
1430static void DumpHals(int out_fd = STDOUT_FILENO) {
Yifan Hong30528a22020-08-07 18:24:06 -07001431 RunCommand("HARDWARE HALS", {"lshal", "--all", "--types=all"},
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001432 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build(),
1433 false, out_fd);
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001434
Steven Moreland44cd9482018-01-04 16:24:13 -08001435 using android::hidl::manager::V1_0::IServiceManager;
1436 using android::hardware::defaultServiceManager;
1437
1438 sp<IServiceManager> sm = defaultServiceManager();
1439 if (sm == nullptr) {
1440 MYLOGE("Could not retrieve hwservicemanager to dump hals.\n");
1441 return;
1442 }
1443
1444 auto ret = sm->list([&](const auto& interfaces) {
1445 for (const std::string& interface : interfaces) {
1446 std::string cleanName = interface;
Steven Morelandc6b1fc22023-07-26 23:53:58 +00001447 std::replace_if(
1448 cleanName.begin(), cleanName.end(),
1449 [](char c) {
1450 return !isalnum(c) && std::string("@-_.").find(c) == std::string::npos;
1451 },
1452 '_');
Nandana Dutt979388e2018-11-30 16:48:55 +00001453 const std::string path = ds.bugreport_internal_dir_ + "/lshal_debug_" + cleanName;
Steven Moreland44cd9482018-01-04 16:24:13 -08001454
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001455 bool empty = false;
Steven Moreland44cd9482018-01-04 16:24:13 -08001456 {
1457 auto fd = android::base::unique_fd(
1458 TEMP_FAILURE_RETRY(open(path.c_str(),
1459 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1460 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1461 if (fd < 0) {
1462 MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str());
1463 continue;
1464 }
1465 RunCommandToFd(fd,
1466 "",
Steven Morelandc81cd3c2018-01-18 14:36:26 -08001467 {"lshal", "debug", "-E", interface},
Steven Moreland44cd9482018-01-04 16:24:13 -08001468 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1469
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001470 empty = 0 == lseek(fd, 0, SEEK_END);
Steven Moreland44cd9482018-01-04 16:24:13 -08001471 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001472 if (!empty) {
1473 ds.EnqueueAddZipEntryAndCleanupIfNeeded("lshal-debug/" + cleanName + ".txt",
1474 path);
1475 } else {
1476 unlink(path.c_str());
1477 }
Steven Moreland44cd9482018-01-04 16:24:13 -08001478 }
1479 });
1480
1481 if (!ret.isOk()) {
1482 MYLOGE("Could not list hals from hwservicemanager.\n");
1483 }
1484}
1485
Devin Moore8df81bb2022-06-08 22:47:02 +00001486// Dump all of the files that make up the vendor interface.
1487// See the files listed in dumpFileList() for the latest list of files.
1488static void DumpVintf() {
Devin Moore16271d92022-09-22 18:28:48 +00001489
1490 const std::string sku = android::base::GetProperty("ro.boot.product.hardware.sku", "");
1491 const auto vintfFiles = android::vintf::details::dumpFileList(sku);
Devin Moore8df81bb2022-06-08 22:47:02 +00001492 for (const auto vintfFile : vintfFiles) {
1493 struct stat st;
1494 if (stat(vintfFile.c_str(), &st) == 0) {
1495 if (S_ISDIR(st.st_mode)) {
1496 ds.AddDir(vintfFile, true /* recursive */);
1497 } else {
1498 ds.EnqueueAddZipEntryAndCleanupIfNeeded(ZIP_ROOT_DIR + vintfFile,
1499 vintfFile);
1500 }
1501 }
1502 }
1503}
1504
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001505static void DumpExternalFragmentationInfo() {
1506 struct stat st;
1507 if (stat("/proc/buddyinfo", &st) != 0) {
1508 MYLOGE("Unable to dump external fragmentation info\n");
1509 return;
1510 }
1511
1512 printf("------ EXTERNAL FRAGMENTATION INFO ------\n");
1513 std::ifstream ifs("/proc/buddyinfo");
1514 auto unusable_index_regex = std::regex{"Node\\s+([0-9]+),\\s+zone\\s+(\\S+)\\s+(.*)"};
1515 for (std::string line; std::getline(ifs, line);) {
1516 std::smatch match_results;
1517 if (std::regex_match(line, match_results, unusable_index_regex)) {
1518 std::stringstream free_pages(std::string{match_results[3]});
1519 std::vector<int> free_pages_per_order(std::istream_iterator<int>{free_pages},
1520 std::istream_iterator<int>());
1521
1522 int total_free_pages = 0;
1523 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1524 total_free_pages += (free_pages_per_order[i] * std::pow(2, i));
1525 }
1526
1527 printf("Node %s, zone %8s", match_results[1].str().c_str(),
1528 match_results[2].str().c_str());
1529
1530 int usable_free_pages = total_free_pages;
1531 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1532 auto unusable_index = (total_free_pages - usable_free_pages) /
1533 static_cast<double>(total_free_pages);
1534 printf(" %5.3f", unusable_index);
1535 usable_free_pages -= (free_pages_per_order[i] * std::pow(2, i));
1536 }
1537
1538 printf("\n");
1539 }
1540 }
1541 printf("\n");
1542}
1543
mhasankd451a472020-05-26 18:02:39 -07001544static void DumpstateLimitedOnly() {
EdenSue8fe4522023-11-20 15:37:23 +08001545 // Trimmed-down version of dumpstate to only include a allowlisted
mhasankd451a472020-05-26 18:02:39 -07001546 // set of logs (system log, event log, and system server / system app
1547 // crashes, and networking logs). See b/136273873 and b/138459828
1548 // for context.
1549 DurationReporter duration_reporter("DUMPSTATE");
1550 unsigned long timeout_ms;
1551 // calculate timeout
1552 timeout_ms = logcat_timeout({"main", "system", "crash"});
1553 RunCommand("SYSTEM LOG",
1554 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1555 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1556 timeout_ms = logcat_timeout({"events"});
1557 RunCommand(
1558 "EVENT LOG",
1559 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1560 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1561
1562 printf("========================================================\n");
1563 printf("== Networking Service\n");
1564 printf("========================================================\n");
1565
1566 RunDumpsys("DUMPSYS NETWORK_SERVICE_LIMITED", {"wifi", "-a"},
1567 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hugo Benichiaa162682020-10-30 23:28:56 +09001568 RunDumpsys("DUMPSYS CONNECTIVITY REQUESTS", {"connectivity", "requests"},
1569 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
mhasankd451a472020-05-26 18:02:39 -07001570
1571 printf("========================================================\n");
Chuwei Hecc54a252024-07-25 15:18:36 +09001572 printf("== Networking Policy\n");
1573 printf("========================================================\n");
1574
1575 RunDumpsys("DUMPSYS NETWORK POLICY", {"netpolicy"}, CommandOptions::WithTimeout(90).Build(),
1576 SEC_TO_MSEC(10));
1577
1578 printf("========================================================\n");
mhasankd451a472020-05-26 18:02:39 -07001579 printf("== Dropbox crashes\n");
1580 printf("========================================================\n");
1581
1582 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1583 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1584
Bryan Yuefb85d92024-02-02 13:37:06 +00001585
1586 printf("========================================================\n");
1587 printf("== ANR Traces\n");
1588 printf("========================================================\n");
1589
Bryan Yucf038cf2024-05-08 09:25:25 +00001590 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX);
Bryan Yuefb85d92024-02-02 13:37:06 +00001591 AddAnrTraceFiles();
1592
mhasankd451a472020-05-26 18:02:39 -07001593 printf("========================================================\n");
1594 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1595 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1596 printf("========================================================\n");
1597 printf("== dumpstate: done (id %d)\n", ds.id_);
1598 printf("========================================================\n");
1599}
1600
Rhed Jaoe017f982020-07-21 17:58:41 +08001601/*
1602 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1603 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1604 * if it's not running in the parallel task.
1605 */
1606static void DumpCheckins(int out_fd = STDOUT_FILENO) {
1607 dprintf(out_fd, "========================================================\n");
1608 dprintf(out_fd, "== Checkins\n");
1609 dprintf(out_fd, "========================================================\n");
1610
1611 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"}, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001612 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"}, out_fd);
1613 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"}, out_fd);
1614 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"}, out_fd);
1615 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"}, out_fd);
1616}
1617
1618/*
1619 * Runs dumpsys on activity service to dump all application activities, services
1620 * and providers in the device.
1621 *
1622 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1623 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1624 * if it's not running in the parallel task.
1625 */
1626static void DumpAppInfos(int out_fd = STDOUT_FILENO) {
1627 dprintf(out_fd, "========================================================\n");
1628 dprintf(out_fd, "== Running Application Activities\n");
1629 dprintf(out_fd, "========================================================\n");
1630
1631 // The following dumpsys internally collects output from running apps, so it can take a long
1632 // time. So let's extend the timeout.
1633
1634 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1635
1636 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1637
1638 dprintf(out_fd, "========================================================\n");
1639 dprintf(out_fd, "== Running Application Services (platform)\n");
1640 dprintf(out_fd, "========================================================\n");
1641
1642 RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
1643 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1644
1645 dprintf(out_fd, "========================================================\n");
1646 dprintf(out_fd, "== Running Application Services (non-platform)\n");
1647 dprintf(out_fd, "========================================================\n");
1648
1649 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1650 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1651
1652 dprintf(out_fd, "========================================================\n");
1653 dprintf(out_fd, "== Running Application Providers (platform)\n");
1654 dprintf(out_fd, "========================================================\n");
1655
1656 RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
Rhed Jaob049f182021-01-11 21:08:43 +08001657 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001658
1659 dprintf(out_fd, "========================================================\n");
1660 dprintf(out_fd, "== Running Application Providers (non-platform)\n");
1661 dprintf(out_fd, "========================================================\n");
1662
1663 RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1664 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1665}
1666
Nandana Dutt5c390032019-03-12 10:52:56 +00001667// Dumps various things. Returns early with status USER_CONSENT_DENIED if user denies consent
1668// via the consent they are shown. Ignores other errors that occur while running various
1669// commands. The consent checking is currently done around long running tasks, which happen to
1670// be distributed fairly evenly throughout the function.
Kean Mariotti306633e2022-09-05 16:30:47 +00001671Dumpstate::RunStatus Dumpstate::dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001672 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001673
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001674 // Enqueue slow functions into the thread pool, if the parallel run is enabled.
Aaron Huang24d215d2022-04-27 18:51:16 +08001675 std::future<std::string> dump_hals, dump_incident_report, dump_board, dump_checkins,
Kean Mariottica20f2d2023-12-15 09:34:25 +00001676 dump_netstats_report;
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001677 if (ds.dump_pool_) {
1678 // Pool was shutdown in DumpstateDefaultAfterCritical method in order to
Kean Mariotti306633e2022-09-05 16:30:47 +00001679 // drop root user. Restarts it.
1680 ds.dump_pool_->start(/* thread_counts = */3);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001681
Chris Morinbc223142022-02-04 14:17:11 -08001682 dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
1683 dump_incident_report = ds.dump_pool_->enqueueTask(
1684 DUMP_INCIDENT_REPORT_TASK, &DumpIncidentReport);
Aaron Huang24d215d2022-04-27 18:51:16 +08001685 dump_netstats_report = ds.dump_pool_->enqueueTask(
1686 DUMP_NETSTATS_PROTO_TASK, &DumpNetstatsProto);
Chris Morinbc223142022-02-04 14:17:11 -08001687 dump_board = ds.dump_pool_->enqueueTaskWithFd(
1688 DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
1689 dump_checkins = ds.dump_pool_->enqueueTaskWithFd(DUMP_CHECKINS_TASK, &DumpCheckins, _1);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001690 }
1691
Nandana Dutt5c390032019-03-12 10:52:56 +00001692 // Dump various things. Note that anything that takes "long" (i.e. several seconds) should
1693 // check intermittently (if it's intrerruptable like a foreach on pids) and/or should be wrapped
1694 // in a consent check (via RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK).
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001695 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001696 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001697 DumpBlockStatFiles();
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001698 DumpFile("MEMORY INFO", "/proc/meminfo");
1699 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001700 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001701
Kevin Jeon947922b2022-09-21 00:29:18 +00001702 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "BUGREPORT_PROCDUMP", {"bugreport_procdump"},
1703 CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001704
Sunny Goyal35949782019-11-19 15:54:36 -08001705 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpVisibleWindowViews);
1706
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001707 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1708 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1709 DumpFile("SLAB INFO", "/proc/slabinfo");
1710 DumpFile("ZONEINFO", "/proc/zoneinfo");
1711 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1712 DumpFile("BUDDYINFO", "/proc/buddyinfo");
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001713 DumpExternalFragmentationInfo();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001714
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001715 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001716
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001717 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001718 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001719
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001720 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001721 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_hals));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001722 } else {
1723 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_HALS_TASK, DumpHals);
1724 }
Steven Moreland81b429e2017-01-31 19:50:46 -08001725
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001726 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001727 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001728 struct stat s;
1729 if (stat("/proc/modules", &s) != 0) {
1730 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1731 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001732 RunCommand("LSMOD", {"lsmod"});
Woody Linc198f252021-05-04 16:37:11 +08001733 RunCommand("MODULES INFO",
1734 {"sh", "-c", "cat /proc/modules | cut -d' ' -f1 | "
1735 " while read MOD ; do echo modinfo:$MOD ; modinfo $MOD ; "
1736 "done"}, CommandOptions::AS_ROOT);
Felipe Lemee4eca582016-06-10 17:48:08 -07001737 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001738
Tom Cherryb87dbfa2020-07-28 11:28:53 -07001739 if (android::base::GetBoolProperty("ro.logd.kernel", false)) {
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001740 DoKernelLogcat();
1741 } else {
1742 do_dmesg();
1743 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001744
Devin Moore8df81bb2022-06-08 22:47:02 +00001745 DumpVintf();
1746
Felipe Lemef0292972016-11-22 13:57:05 -08001747 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001748
Jeff Brown1dc94e32014-09-11 14:15:27 -07001749 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001750 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001751
Jack Yu5a6b2e22020-08-14 18:13:35 +08001752 /* Dump Nfc NCI logs */
1753 ds.AddDir("/data/misc/nfc/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001754
Paul Chang0d2aad72020-02-13 20:04:03 +08001755 if (ds.options_->do_screenshot && !ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001756 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001757 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001758 }
1759
Felipe Lemee184f662016-10-27 10:04:47 -07001760 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001761
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001762 MaybeAddSystemTraceToZip();
1763
Narayan Kamath8f788292017-05-25 13:20:39 +01001764 // NOTE: tombstones are always added as separate entries in the zip archive
1765 // and are not interspersed with the main report.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001766 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
Narayan Kamathbd863722017-06-01 18:50:12 +01001767 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001768 if (!tombstones_dumped) {
1769 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001770 }
1771
Jayachandran Ca94c7172017-06-10 15:08:12 -07001772 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001773
Lorenzo Colitti807f2dd2022-05-27 12:48:37 +09001774 RunDumpsys("EBPF MAP STATS", {"connectivity", "trafficcontroller"});
Chenbo Feng276a3b62018-08-07 11:44:49 -07001775
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001776 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001777
Alessio Balsini9e332a72024-12-10 15:31:57 +00001778 DumpKernelMemoryAllocations();
1779
Woody Lin20767a92022-11-29 15:50:24 +08001780 DumpShutdownCheckpoints();
1781
Jayachandran Ca94c7172017-06-10 15:08:12 -07001782 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001783
1784 dump_route_tables();
1785
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001786 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1787 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1788 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001789
Nandana Dutt5c390032019-03-12 10:52:56 +00001790 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysHigh);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001791
Chiachang Wang668ede42021-05-17 17:14:20 +08001792 // The dump mechanism in connectivity is refactored due to modularization work. Connectivity can
1793 // only register with a default priority(NORMAL priority). Dumpstate has to call connectivity
1794 // dump with priority parameters to dump high priority information.
1795 RunDumpsys("SERVICE HIGH connectivity", {"connectivity", "--dump-priority", "HIGH"},
1796 CommandOptions::WithTimeout(10).Build());
1797
Elliott Hughes23ccc622017-02-28 10:14:22 -08001798 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001799
Joe Onoratod38bc3a2023-06-29 15:48:28 -07001800 DumpFile("SYSTEM BUILD-TIME RELEASE FLAGS", "/system/etc/build_flags.json");
1801 DumpFile("SYSTEM_EXT BUILD-TIME RELEASE FLAGS", "/system_ext/etc/build_flags.json");
1802 DumpFile("PRODUCT BUILD-TIME RELEASE FLAGS", "/product/etc/build_flags.json");
1803 DumpFile("VENDOR BUILD-TIME RELEASE FLAGS", "/vendor/etc/build_flags.json");
1804
MÃ¥rten Kongstad5ad813f2023-09-28 10:09:18 +02001805 RunCommand("ACONFIG FLAGS", {PRINT_FLAGS},
1806 CommandOptions::WithTimeout(10).Always().DropRoot().Build());
Ted Bauerf6d61b82024-09-13 19:57:19 +00001807 RunCommand("ACONFIG FLAGS DUMP", {AFLAGS, "list"},
1808 CommandOptions::WithTimeout(10).Always().AsRootIfAvailable().Build());
1809 RunCommand("WHICH ACONFIG FLAG STORAGE", {AFLAGS, "which-backing"},
1810 CommandOptions::WithTimeout(10).Always().AsRootIfAvailable().Build());
Joe Onoratod38bc3a2023-06-29 15:48:28 -07001811
Jin Qianf334d662017-10-10 14:41:37 -07001812 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001813
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001814 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001815
Colin Crossf45fa6b2012-03-26 12:38:26 -07001816 /* Binder state is expensive to look at as it uses a lot of memory. */
Hridya Valsaraju920ba712020-02-09 16:27:01 -08001817 std::string binder_logs_dir = access("/dev/binderfs/binder_logs", R_OK) ?
1818 "/sys/kernel/debug/binder" : "/dev/binderfs/binder_logs";
1819
1820 DumpFile("BINDER FAILED TRANSACTION LOG", binder_logs_dir + "/failed_transaction_log");
1821 DumpFile("BINDER TRANSACTION LOG", binder_logs_dir + "/transaction_log");
1822 DumpFile("BINDER TRANSACTIONS", binder_logs_dir + "/transactions");
1823 DumpFile("BINDER STATS", binder_logs_dir + "/stats");
1824 DumpFile("BINDER STATE", binder_logs_dir + "/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001825
Yifan Hongd90cc652020-02-08 16:52:02 -08001826 ds.AddDir(SNAPSHOTCTL_LOG_DIR, false);
1827
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001828 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001829 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_board));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001830 } else {
1831 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
1832 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001833
Steven Moreland7440ddb2016-12-15 16:13:39 -08001834 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001835 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1836 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001837 // su does not exist on user builds, so try running without it.
1838 // This way any implementations of vril-dump that do not require
1839 // root can run on user builds.
1840 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001841 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001842 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001843 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001844 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001845 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001846 }
1847
Felipe Lemed8b94e52016-12-08 10:21:44 -08001848 printf("========================================================\n");
1849 printf("== Android Framework Services\n");
1850 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001851
Nandana Dutt5c390032019-03-12 10:52:56 +00001852 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001853
Jack He91ff2fe2021-02-18 18:23:43 -08001854 /* Dump Bluetooth HCI logs after getting bluetooth_manager dumpsys */
1855 ds.AddDir("/data/misc/bluetooth/logs", true);
1856
Rhed Jaoe017f982020-07-21 17:58:41 +08001857 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001858 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_checkins));
Rhed Jaoe017f982020-07-21 17:58:41 +08001859 } else {
1860 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_CHECKINS_TASK, DumpCheckins);
1861 }
Dianne Hackborn02bea972013-06-26 18:59:09 -07001862
Rhed Jaoc5f7ec32020-12-22 22:11:08 +08001863 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpAppInfos);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001864
Adrian Roos8b397ab2017-04-04 16:35:44 -07001865 printf("========================================================\n");
1866 printf("== Dropbox crashes\n");
1867 printf("========================================================\n");
1868
1869 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1870 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1871
Felipe Lemed8b94e52016-12-08 10:21:44 -08001872 printf("========================================================\n");
1873 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1874 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1875 printf("========================================================\n");
1876 printf("== dumpstate: done (id %d)\n", ds.id_);
1877 printf("========================================================\n");
Bookatz38472142018-09-28 10:20:24 -07001878
1879 printf("========================================================\n");
1880 printf("== Obtaining statsd metadata\n");
1881 printf("========================================================\n");
1882 // This differs from the usual dumpsys stats, which is the stats report data.
1883 RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
Mike Ma5c267872019-08-21 11:31:34 -07001884
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +09001885 // Add linker configuration directory
1886 ds.AddDir(LINKERCONFIG_DIR, true);
1887
Li Li830179f2022-01-04 12:53:29 -08001888 /* Dump frozen cgroupfs */
1889 dump_frozen_cgroupfs();
Li Li2eedd412021-06-30 15:11:53 -07001890
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001891 if (ds.dump_pool_) {
Aaron Huang24d215d2022-04-27 18:51:16 +08001892 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_netstats_report));
1893 } else {
1894 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_NETSTATS_PROTO_TASK,
1895 DumpNetstatsProto);
1896 }
1897
1898 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001899 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_incident_report));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001900 } else {
1901 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_INCIDENT_REPORT_TASK,
1902 DumpIncidentReport);
1903 }
Mike Ma5c267872019-08-21 11:31:34 -07001904
Kean Mariotti306633e2022-09-05 16:30:47 +00001905 MaybeAddUiTracesToZip();
1906
Nandana Dutt5c390032019-03-12 10:52:56 +00001907 return Dumpstate::RunStatus::OK;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001908}
1909
Nandana Dutt5c390032019-03-12 10:52:56 +00001910/*
1911 * Dumps state for the default case; drops root after it's no longer necessary.
1912 *
1913 * Returns RunStatus::OK if everything went fine.
1914 * Returns RunStatus::ERROR if there was an error.
1915 * Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport
1916 * with the caller.
1917 */
Jichao Lie89d9c12019-11-21 19:02:51 -08001918Dumpstate::RunStatus Dumpstate::DumpstateDefaultAfterCritical() {
Nandana Duttdb379fa2019-10-09 16:54:41 +01001919 // Capture first logcat early on; useful to take a snapshot before dumpstate logs take over the
1920 // buffer.
1921 DoLogcat();
1922 // Capture timestamp after first logcat to use in next logcat
1923 time_t logcat_ts = time(nullptr);
1924
Nandana Dutt4be45d12018-09-26 15:04:23 +01001925 /* collect stack traces from Dalvik and native processes (needs root) */
Chris Morinbc223142022-02-04 14:17:11 -08001926 std::future<std::string> dump_traces;
Rhed Jao5377d792020-07-16 17:37:39 +08001927 if (dump_pool_) {
1928 RETURN_IF_USER_DENIED_CONSENT();
1929 // One thread is enough since we only need to enqueue DumpTraces here.
1930 dump_pool_->start(/* thread_counts = */1);
1931
1932 // DumpTraces takes long time, post it to the another thread in the
1933 // pool, if pool is available
Chris Morinbc223142022-02-04 14:17:11 -08001934 dump_traces = dump_pool_->enqueueTask(
1935 DUMP_TRACES_TASK, &Dumpstate::DumpTraces, &ds, &dump_traces_path);
Rhed Jao5377d792020-07-16 17:37:39 +08001936 } else {
1937 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_TRACES_TASK, ds.DumpTraces,
1938 &dump_traces_path);
1939 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001940
1941 /* Run some operations that require root. */
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001942 if (!PropertiesHelper::IsDryRun()) {
Chris Morinc2cba7a2022-02-01 17:06:50 -08001943 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX);
1944 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX);
Andy Hungd62f7e62024-01-11 15:47:52 -08001945 ds.anr_trace_data_ = GetDumpFds(ANR_DIR, ANR_TRACE_FILE_PREFIX);
Woody Lin20767a92022-11-29 15:50:24 +08001946 ds.shutdown_checkpoints_ = GetDumpFds(
1947 SHUTDOWN_CHECKPOINTS_DIR, SHUTDOWN_CHECKPOINTS_FILE_PREFIX);
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001948 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001949
1950 ds.AddDir(RECOVERY_DIR, true);
1951 ds.AddDir(RECOVERY_DATA_DIR, true);
1952 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
Kelvin Zhang6eaa0f92022-09-12 09:29:19 -07001953 ds.AddDir(UPDATE_ENGINE_PREF_DIR, true);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001954 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1955 if (!PropertiesHelper::IsUserBuild()) {
1956 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1957 ds.AddDir(PROFILE_DATA_DIR_REF, true);
Calin Juravlef84d3692020-04-28 15:31:12 -07001958 ds.AddZipEntry(ZIP_ROOT_DIR + PACKAGE_DEX_USE_LIST, PACKAGE_DEX_USE_LIST);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001959 }
Jerry Changa1df8a92020-01-02 16:03:39 +08001960 ds.AddDir(PREREBOOT_DATA_DIR, false);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001961 add_mountinfo();
Peter Collingbourne78aa2942023-02-15 14:50:31 -08001962 for (const char* path : {"/proc/cpuinfo", "/proc/meminfo"}) {
1963 ds.AddZipEntry(ZIP_ROOT_DIR + path, path);
1964 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001965 DumpIpTablesAsRoot();
David Andersond9ba4752018-12-11 18:26:59 -08001966 DumpDynamicPartitionInfo();
Yifan Hong3945e1b2019-10-29 12:59:23 -07001967 ds.AddDir(OTA_METADATA_DIR, true);
Jeff Sharkey9df29d52023-02-06 14:26:30 -07001968 if (!PropertiesHelper::IsUserBuild()) {
1969 // Include dropbox entry files inside ZIP, but exclude
1970 // noisy WTF and StrictMode entries
1971 dump_files("", DROPBOX_DIR, skip_wtf_strictmode, _add_file_from_fd);
1972 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001973
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001974 // Capture any IPSec policies in play. No keys are exposed here.
Nandana Dutt4be45d12018-09-26 15:04:23 +01001975 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1976
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001977 // Dump IPsec stats. No keys are exposed here.
1978 DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
1979
Nandana Dutt4be45d12018-09-26 15:04:23 +01001980 // Run ss as root so we can see socket marks.
1981 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1982
1983 // Run iotop as root to show top 100 IO threads
1984 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1985
Erick Reyese68df822019-02-11 14:46:36 -08001986 // Gather shared memory buffer info if the product implements it
Hridya Valsaraju1da80c52021-01-09 22:10:11 -08001987 RunCommand("Dmabuf dump", {"dmabuf_dump"});
1988 RunCommand("Dmabuf per-buffer/per-exporter/per-device stats", {"dmabuf_dump", "-b"});
Erick Reyese68df822019-02-11 14:46:36 -08001989
Minchan Kim22c6a1e2019-09-30 15:58:10 -07001990 DumpFile("PSI cpu", "/proc/pressure/cpu");
1991 DumpFile("PSI memory", "/proc/pressure/memory");
1992 DumpFile("PSI io", "/proc/pressure/io");
1993
Steven Moreland9379c462023-12-21 02:04:27 +00001994 ds.AddZipEntry(ZIP_ROOT_DIR + KERNEL_CONFIG, KERNEL_CONFIG);
1995
MÃ¥rten Kongstad60195a72022-09-20 14:14:20 +02001996 RunCommand("SDK EXTENSIONS", {SDK_EXT_INFO, "--dump"},
1997 CommandOptions::WithTimeout(10).Always().DropRoot().Build());
1998
Nattharat Jariyanuntanaetb250cae2024-05-15 07:48:19 +00001999 // Dump UWB UCI logs here because apexdata requires root access
2000 ds.AddDir(UWB_LOG_DIR, true);
2001
Rhed Jao5377d792020-07-16 17:37:39 +08002002 if (dump_pool_) {
2003 RETURN_IF_USER_DENIED_CONSENT();
Chris Morinbc223142022-02-04 14:17:11 -08002004 WaitForTask(std::move(dump_traces));
Rhed Jao5377d792020-07-16 17:37:39 +08002005
Chris Morinbc223142022-02-04 14:17:11 -08002006 // Current running thread in the pool is the root user also. Delete
2007 // the pool and make a new one later to ensure none of threads in the pool are root.
2008 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao5377d792020-07-16 17:37:39 +08002009 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01002010 if (!DropRootUser()) {
Nandana Dutt5c390032019-03-12 10:52:56 +00002011 return Dumpstate::RunStatus::ERROR;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002012 }
2013
Nandana Dutt5c390032019-03-12 10:52:56 +00002014 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttdb379fa2019-10-09 16:54:41 +01002015 Dumpstate::RunStatus status = dumpstate();
2016 // Capture logcat since the last time we did it.
2017 DoSystemLogcat(logcat_ts);
2018 return status;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002019}
2020
Rhed Jaob5685b32020-08-14 17:19:17 +08002021// Common states for telephony and wifi which are needed to be collected before
2022// dumpstate drop the root user.
2023static void DumpstateRadioAsRoot() {
2024 DumpIpTablesAsRoot();
2025 ds.AddDir(LOGPERSIST_DATA_DIR, false);
2026}
2027
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002028// This method collects common dumpsys for telephony and wifi. Typically, wifi
2029// reports are fine to include all information, but telephony reports on user
2030// builds need to strip some content (see DumpstateTelephonyOnly).
2031static void DumpstateRadioCommon(bool include_sensitive_info = true) {
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002032 // We need to be picky about some stuff for telephony reports on user builds.
2033 if (!include_sensitive_info) {
2034 // Only dump the radio log buffer (other buffers and dumps contain too much unrelated info).
2035 DoRadioLogcat();
2036 } else {
Rhed Jaob5685b32020-08-14 17:19:17 +08002037 // DumpHals takes long time, post it to the another thread in the pool,
2038 // if pool is available.
Chris Morinbc223142022-02-04 14:17:11 -08002039 std::future<std::string> dump_hals;
Rhed Jaob5685b32020-08-14 17:19:17 +08002040 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002041 dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
Rhed Jaob5685b32020-08-14 17:19:17 +08002042 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002043 // Contains various system properties and process startup info.
2044 do_dmesg();
2045 // Logs other than the radio buffer may contain package/component names and potential PII.
2046 DoLogcat();
2047 // Too broad for connectivity problems.
2048 DoKmsg();
Rhed Jaob5685b32020-08-14 17:19:17 +08002049 // DumpHals contains unrelated hardware info (camera, NFC, biometrics, ...).
2050 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002051 WaitForTask(std::move(dump_hals));
Rhed Jaob5685b32020-08-14 17:19:17 +08002052 } else {
2053 RUN_SLOW_FUNCTION_AND_LOG(DUMP_HALS_TASK, DumpHals);
2054 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002055 }
2056
Jayachandran Ca94c7172017-06-10 15:08:12 -07002057 DumpPacketStats();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002058 DumpIpAddrAndRules();
2059 dump_route_tables();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002060 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
2061 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08002062}
2063
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002064// We use "telephony" here for legacy reasons, though this now really means "connectivity" (cellular
2065// + wifi + networking). This method collects dumpsys for connectivity debugging only. General rules
2066// for what can be included on user builds: all reported information MUST directly relate to
2067// connectivity debugging or customer support and MUST NOT contain unrelated personally identifiable
2068// information. This information MUST NOT identify user-installed packages (UIDs are OK, package
2069// names are not), and MUST NOT contain logs of user application traffic.
2070// TODO(b/148168577) rename this and other related fields/methods to "connectivity" instead.
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08002071static void DumpstateTelephonyOnly(const std::string& calling_package) {
mukesh agrawal253dad42018-01-23 21:59:59 -08002072 DurationReporter duration_reporter("DUMPSTATE");
Jichao Lie89d9c12019-11-21 19:02:51 -08002073
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002074 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
mukesh agrawal253dad42018-01-23 21:59:59 -08002075
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002076 const bool include_sensitive_info = !PropertiesHelper::IsUserBuild();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002077
Rhed Jaob5685b32020-08-14 17:19:17 +08002078 DumpstateRadioAsRoot();
2079 if (!DropRootUser()) {
2080 return;
2081 }
2082
2083 // Starts thread pool after the root user is dropped, and two additional threads
2084 // are created for DumpHals in the DumpstateRadioCommon and DumpstateBoard.
Chris Morinbc223142022-02-04 14:17:11 -08002085 std::future<std::string> dump_board;
Rhed Jaob5685b32020-08-14 17:19:17 +08002086 if (ds.dump_pool_) {
2087 ds.dump_pool_->start(/*thread_counts =*/2);
2088
2089 // DumpstateBoard takes long time, post it to the another thread in the pool,
2090 // if pool is available.
Chris Morinbc223142022-02-04 14:17:11 -08002091 dump_board = ds.dump_pool_->enqueueTaskWithFd(
2092 DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
Rhed Jaob5685b32020-08-14 17:19:17 +08002093 }
2094
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002095 DumpstateRadioCommon(include_sensitive_info);
2096
2097 if (include_sensitive_info) {
2098 // Contains too much unrelated PII, and given the unstructured nature of sysprops, we can't
2099 // really cherrypick all of the connectivity-related ones. Apps generally have no business
2100 // reading these anyway, and there should be APIs to supply the info in a more app-friendly
2101 // way.
2102 RunCommand("SYSTEM PROPERTIES", {"getprop"});
2103 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002104
2105 printf("========================================================\n");
2106 printf("== Android Framework Services\n");
2107 printf("========================================================\n");
2108
Vishnu Nair652cc802017-11-30 15:18:30 -08002109 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2110 SEC_TO_MSEC(10));
Hunter Knepshield31cbae12021-05-11 16:23:24 -07002111 RunDumpsys("DUMPSYS", {"vcn_management"}, CommandOptions::WithTimeout(90).Build(),
2112 SEC_TO_MSEC(10));
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08002113 if (include_sensitive_info) {
2114 // Carrier apps' services will be dumped below in dumpsys activity service all-non-platform.
2115 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
2116 SEC_TO_MSEC(10));
2117 } else {
2118 // If the caller is a carrier app and has a carrier service, dump it here since we aren't
2119 // running dumpsys activity service all-non-platform below. Due to the increased output, we
2120 // give a higher timeout as well.
2121 RunDumpsys("DUMPSYS", {"carrier_config", "--requesting-package", calling_package},
2122 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(30));
2123 }
2124 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002125 RunDumpsys("DUMPSYS", {"netpolicy"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2126 RunDumpsys("DUMPSYS", {"network_management"}, CommandOptions::WithTimeout(90).Build(),
Sooraj Sasindrane8d98912018-04-20 11:31:55 -07002127 SEC_TO_MSEC(10));
Hunter Knepshield0fe51b12020-03-05 16:58:20 -08002128 RunDumpsys("DUMPSYS", {"telephony.registry"}, CommandOptions::WithTimeout(90).Build(),
2129 SEC_TO_MSEC(10));
Jack Yu773cc032023-03-16 22:43:39 -07002130 RunDumpsys("DUMPSYS", {"isub"}, CommandOptions::WithTimeout(90).Build(),
2131 SEC_TO_MSEC(10));
Grant Menke56698972023-02-24 13:11:07 -08002132 RunDumpsys("DUMPSYS", {"telecom"}, CommandOptions::WithTimeout(90).Build(),
2133 SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002134 if (include_sensitive_info) {
2135 // Contains raw IP addresses, omit from reports on user builds.
2136 RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2137 // Contains raw destination IP/MAC addresses, omit from reports on user builds.
2138 RunDumpsys("DUMPSYS", {"connmetrics"}, CommandOptions::WithTimeout(90).Build(),
2139 SEC_TO_MSEC(10));
2140 // Contains package/component names, omit from reports on user builds.
2141 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
2142 SEC_TO_MSEC(10));
2143 // Contains package names, but should be relatively simple to remove them (also contains
2144 // UIDs already), omit from reports on user builds.
2145 RunDumpsys("BATTERYSTATS", {"deviceidle"}, CommandOptions::WithTimeout(90).Build(),
2146 SEC_TO_MSEC(10));
2147 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002148
2149 printf("========================================================\n");
2150 printf("== Running Application Services\n");
2151 printf("========================================================\n");
2152
2153 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
2154
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002155 if (include_sensitive_info) {
2156 printf("========================================================\n");
2157 printf("== Running Application Services (non-platform)\n");
2158 printf("========================================================\n");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002159
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002160 // Contains package/component names and potential PII, omit from reports on user builds.
2161 // To get dumps of the active CarrierService(s) on user builds, we supply an argument to the
2162 // carrier_config dumpsys instead.
2163 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
2164 DUMPSYS_COMPONENTS_OPTIONS);
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002165
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002166 printf("========================================================\n");
2167 printf("== Checkins\n");
2168 printf("========================================================\n");
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002169
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002170 // Contains package/component names, omit from reports on user builds.
2171 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
2172 }
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002173
2174 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07002175 printf("== dumpstate: done (id %d)\n", ds.id_);
2176 printf("========================================================\n");
Rhed Jaob5685b32020-08-14 17:19:17 +08002177
2178 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002179 WaitForTask(std::move(dump_board));
Rhed Jaob5685b32020-08-14 17:19:17 +08002180 } else {
2181 RUN_SLOW_FUNCTION_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
2182 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002183}
2184
mukesh agrawal253dad42018-01-23 21:59:59 -08002185// This method collects dumpsys for wifi debugging only
2186static void DumpstateWifiOnly() {
2187 DurationReporter duration_reporter("DUMPSTATE");
2188
Rhed Jaob5685b32020-08-14 17:19:17 +08002189 DumpstateRadioAsRoot();
2190 if (!DropRootUser()) {
2191 return;
2192 }
2193
2194 // Starts thread pool after the root user is dropped. Only one additional
2195 // thread is needed for DumpHals in the DumpstateRadioCommon.
2196 if (ds.dump_pool_) {
2197 ds.dump_pool_->start(/*thread_counts =*/1);
2198 }
2199
mukesh agrawal253dad42018-01-23 21:59:59 -08002200 DumpstateRadioCommon();
2201
2202 printf("========================================================\n");
2203 printf("== Android Framework Services\n");
2204 printf("========================================================\n");
2205
2206 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2207 SEC_TO_MSEC(10));
2208 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
2209 SEC_TO_MSEC(10));
2210
2211 printf("========================================================\n");
2212 printf("== dumpstate: done (id %d)\n", ds.id_);
2213 printf("========================================================\n");
2214}
2215
Elis Elliott8e401ad2023-08-08 11:18:59 +00002216// Collects a lightweight dumpstate to be used for debugging onboarding related flows.
2217static void DumpstateOnboardingOnly() {
2218 ds.AddDir(LOGPERSIST_DATA_DIR, false);
2219}
2220
Christopher Ferris83e0e842024-05-31 13:13:34 -07002221static std::string GetTimestamp(const timespec& ts) {
2222 tm tm;
2223 localtime_r(&ts.tv_sec, &tm);
2224
2225 // Reserve enough space for the entire time string, includes the space
2226 // for the '\0' to make the calculations below easier by using size for
2227 // the total string size.
2228 std::string str(sizeof("1970-01-01 00:00:00.123456789+0830"), '\0');
2229 size_t n = strftime(str.data(), str.size(), "%F %H:%M", &tm);
2230 if (n == 0) {
2231 return "TIMESTAMP FAILURE";
2232 }
2233 int num_chars = snprintf(&str[n], str.size() - n, ":%02d.%09ld", tm.tm_sec, ts.tv_nsec);
2234 if (num_chars > str.size() - n) {
2235 return "TIMESTAMP FAILURE";
2236 }
2237 n += static_cast<size_t>(num_chars);
2238 if (strftime(&str[n], str.size() - n, "%z", &tm) == 0) {
2239 return "TIMESTAMP FAILURE";
2240 }
2241 return str;
2242}
2243
2244static std::string GetCmdline(pid_t pid) {
2245 std::string cmdline;
2246 if (!android::base::ReadFileToString(android::base::StringPrintf("/proc/%d/cmdline", pid),
2247 &cmdline)) {
2248 return "UNKNOWN";
2249 }
2250 // There are '\0' terminators between arguments, convert them to spaces.
2251 // But start by skipping all trailing '\0' values.
2252 size_t cur = cmdline.size() - 1;
2253 while (cur != 0 && cmdline[cur] == '\0') {
2254 cur--;
2255 }
2256 if (cur == 0) {
2257 return "UNKNOWN";
2258 }
2259 while ((cur = cmdline.rfind('\0', cur)) != std::string::npos) {
2260 cmdline[cur] = ' ';
2261 }
2262 return cmdline;
2263}
2264
2265static void DumpPidHeader(int fd, pid_t pid, const timespec& ts) {
2266 // For consistency, the header to this message matches the one
2267 // dumped by debuggerd.
2268 dprintf(fd, "\n----- pid %d at %s -----\n", pid, GetTimestamp(ts).c_str());
2269 dprintf(fd, "Cmd line: %s\n", GetCmdline(pid).c_str());
2270}
2271
2272static void DumpPidFooter(int fd, pid_t pid) {
2273 // For consistency, the footer to this message matches the one
2274 // dumped by debuggerd.
2275 dprintf(fd, "----- end %d -----\n", pid);
2276}
2277
2278static bool DumpBacktrace(int fd, pid_t pid, bool is_java_process) {
2279 int ret = dump_backtrace_to_file_timeout(
2280 pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace, 3, fd);
2281 if (ret == -1 && is_java_process) {
2282 // Tried to unwind as a java process, try a native unwind.
2283 dprintf(fd, "Java unwind failed for pid %d, trying a native unwind.\n", pid);
2284 ret = dump_backtrace_to_file_timeout(pid, kDebuggerdNativeBacktrace, 3, fd);
2285 }
2286 return ret != -1;
2287}
2288
Nandana Duttcf419a72019-03-14 10:40:17 +00002289Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
Gavin Corkery789d7a52021-02-24 23:52:35 +00002290 const std::string temp_file_pattern = ds.bugreport_internal_dir_ + "/dumptrace_XXXXXX";
Nandana Duttfaafd522019-03-11 09:23:09 +00002291 const size_t buf_size = temp_file_pattern.length() + 1;
2292 std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
2293 memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
2294
2295 // Create a new, empty file to receive all trace dumps.
2296 //
2297 // TODO: This can be simplified once we remove support for the old style
2298 // dumps. We can have a file descriptor passed in to dump_traces instead
2299 // of creating a file, closing it and then reopening it again.
2300 android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
2301 if (fd < 0) {
2302 MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002303 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002304 }
2305
2306 // Nobody should have access to this temporary file except dumpstate, but we
2307 // temporarily grant 'read' to 'others' here because this file is created
2308 // when tombstoned is still running as root, but dumped after dropping. This
2309 // can go away once support for old style dumping has.
2310 const int chmod_ret = fchmod(fd, 0666);
2311 if (chmod_ret < 0) {
2312 MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002313 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002314 }
2315
2316 std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
2317 if (proc.get() == nullptr) {
2318 MYLOGE("opendir /proc failed: %s\n", strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002319 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002320 }
2321
2322 // Number of times process dumping has timed out. If we encounter too many
2323 // failures, we'll give up.
2324 int timeout_failures = 0;
2325 bool dalvik_found = false;
2326
Jayant Chowdharya0a8eb22022-05-20 03:30:09 +00002327 const std::set<int> hal_pids = get_interesting_pids();
Nandana Duttfaafd522019-03-11 09:23:09 +00002328
2329 struct dirent* d;
2330 while ((d = readdir(proc.get()))) {
Nandana Duttcf419a72019-03-14 10:40:17 +00002331 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttfaafd522019-03-11 09:23:09 +00002332 int pid = atoi(d->d_name);
2333 if (pid <= 0) {
2334 continue;
2335 }
2336
2337 const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
2338 std::string exe;
2339 if (!android::base::Readlink(link_name, &exe)) {
2340 continue;
2341 }
2342
2343 bool is_java_process;
2344 if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
2345 // Don't bother dumping backtraces for the zygote.
2346 if (IsZygote(pid)) {
2347 continue;
2348 }
2349
2350 dalvik_found = true;
2351 is_java_process = true;
2352 } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
2353 is_java_process = false;
2354 } else {
2355 // Probably a native process we don't care about, continue.
2356 continue;
2357 }
2358
2359 // If 3 backtrace dumps fail in a row, consider debuggerd dead.
2360 if (timeout_failures == 3) {
2361 dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
2362 break;
2363 }
2364
Christopher Ferris83e0e842024-05-31 13:13:34 -07002365 timespec start_timespec;
2366 clock_gettime(CLOCK_REALTIME, &start_timespec);
2367 if (IsCached(pid)) {
2368 DumpPidHeader(fd, pid, start_timespec);
2369 dprintf(fd, "Process is cached, skipping backtrace due to high chance of timeout.\n");
2370 DumpPidFooter(fd, pid);
2371 continue;
2372 }
Nandana Duttfaafd522019-03-11 09:23:09 +00002373
Christopher Ferris83e0e842024-05-31 13:13:34 -07002374 const uint64_t start = Nanotime();
2375 if (!DumpBacktrace(fd, pid, is_java_process)) {
2376 if (IsCached(pid)) {
2377 DumpPidHeader(fd, pid, start_timespec);
2378 dprintf(fd, "Backtrace failed, but process has become cached.\n");
2379 DumpPidFooter(fd, pid);
2380 continue;
2381 }
2382
2383 DumpPidHeader(fd, pid, start_timespec);
2384 dprintf(fd, "Backtrace gathering failed, likely due to a timeout.\n");
2385 DumpPidFooter(fd, pid);
2386
2387 dprintf(fd, "\n[dump %s stack %d: %.3fs elapsed]\n",
2388 is_java_process ? "dalvik" : "native", pid,
2389 (float)(Nanotime() - start) / NANOS_PER_SEC);
Nandana Duttfaafd522019-03-11 09:23:09 +00002390 timeout_failures++;
2391 continue;
2392 }
2393
2394 // We've successfully dumped stack traces, reset the failure count
2395 // and write a summary of the elapsed time to the file and continue with the
2396 // next process.
2397 timeout_failures = 0;
2398
2399 dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
2400 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
2401 }
2402
2403 if (!dalvik_found) {
2404 MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
2405 }
2406
Nandana Duttcf419a72019-03-14 10:40:17 +00002407 *path = file_name_buf.release();
2408 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002409}
2410
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002411static dumpstate_hal_hidl::DumpstateMode GetDumpstateHalModeHidl(
2412 const Dumpstate::BugreportMode bugreport_mode) {
2413 switch (bugreport_mode) {
2414 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2415 return dumpstate_hal_hidl::DumpstateMode::FULL;
2416 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2417 return dumpstate_hal_hidl::DumpstateMode::INTERACTIVE;
2418 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2419 return dumpstate_hal_hidl::DumpstateMode::REMOTE;
2420 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2421 return dumpstate_hal_hidl::DumpstateMode::WEAR;
2422 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2423 return dumpstate_hal_hidl::DumpstateMode::CONNECTIVITY;
2424 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2425 return dumpstate_hal_hidl::DumpstateMode::WIFI;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002426 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002427 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2428 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2429 }
2430 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2431}
2432
2433static dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode GetDumpstateHalModeAidl(
2434 const Dumpstate::BugreportMode bugreport_mode) {
2435 switch (bugreport_mode) {
2436 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2437 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::FULL;
2438 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2439 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::INTERACTIVE;
2440 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2441 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::REMOTE;
2442 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2443 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WEAR;
2444 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2445 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::CONNECTIVITY;
2446 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2447 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WIFI;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002448 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002449 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2450 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2451 }
2452 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2453}
2454
2455static void DoDumpstateBoardHidl(
2456 const sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_1_0,
2457 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2458 const Dumpstate::BugreportMode bugreport_mode,
2459 const size_t timeout_sec) {
2460
2461 using ScopedNativeHandle =
2462 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
2463 ScopedNativeHandle handle(native_handle_create(static_cast<int>(dumpstate_fds.size()), 0),
2464 [](native_handle_t* handle) {
2465 // we don't close file handle's here
2466 // via native_handle_close(handle)
2467 // instead we let dumpstate_fds close the file handles when
2468 // dumpstate_fds gets destroyed
2469 native_handle_delete(handle);
2470 });
2471 if (handle == nullptr) {
2472 MYLOGE("Could not create native_handle for dumpstate HAL\n");
2473 return;
2474 }
2475
2476 for (size_t i = 0; i < dumpstate_fds.size(); i++) {
2477 handle.get()->data[i] = dumpstate_fds[i].get();
2478 }
2479
2480 // Prefer version 1.1 if available. New devices launching with R are no longer allowed to
2481 // implement just 1.0.
2482 const char* descriptor_to_kill;
2483 using DumpstateBoardTask = std::packaged_task<bool()>;
2484 DumpstateBoardTask dumpstate_board_task;
2485 sp<dumpstate_hal_hidl::IDumpstateDevice> dumpstate_hal(
2486 dumpstate_hal_hidl::IDumpstateDevice::castFrom(dumpstate_hal_1_0));
2487 if (dumpstate_hal != nullptr) {
2488 MYLOGI("Using IDumpstateDevice v1.1 HIDL HAL");
2489
2490 dumpstate_hal_hidl::DumpstateMode dumpstate_hal_mode =
2491 GetDumpstateHalModeHidl(bugreport_mode);
2492
2493 descriptor_to_kill = dumpstate_hal_hidl::IDumpstateDevice::descriptor;
2494 dumpstate_board_task =
2495 DumpstateBoardTask([timeout_sec, dumpstate_hal_mode, dumpstate_hal, &handle]() -> bool {
2496 ::android::hardware::Return<dumpstate_hal_hidl::DumpstateStatus> status =
2497 dumpstate_hal->dumpstateBoard_1_1(handle.get(), dumpstate_hal_mode,
2498 SEC_TO_MSEC(timeout_sec));
2499 if (!status.isOk()) {
2500 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2501 return false;
2502 } else if (status != dumpstate_hal_hidl::DumpstateStatus::OK) {
2503 MYLOGE("dumpstateBoard failed with DumpstateStatus::%s\n",
2504 dumpstate_hal_hidl::toString(status).c_str());
2505 return false;
2506 }
2507 return true;
2508 });
2509 } else {
2510 MYLOGI("Using IDumpstateDevice v1.0 HIDL HAL");
2511
2512 descriptor_to_kill = dumpstate_hal_hidl_1_0::IDumpstateDevice::descriptor;
2513 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal_1_0, &handle]() -> bool {
2514 ::android::hardware::Return<void> status =
2515 dumpstate_hal_1_0->dumpstateBoard(handle.get());
2516 if (!status.isOk()) {
2517 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2518 return false;
2519 }
2520 return true;
2521 });
2522 }
2523 auto result = dumpstate_board_task.get_future();
2524 std::thread(std::move(dumpstate_board_task)).detach();
2525
2526 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2527 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2528 if (!android::base::SetProperty(
2529 "ctl.interface_restart",
2530 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2531 MYLOGE("Couldn't restart dumpstate HAL\n");
2532 }
2533 }
2534 // Wait some time for init to kill dumpstate vendor HAL
2535 constexpr size_t killing_timeout_sec = 10;
2536 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2537 MYLOGE(
2538 "killing dumpstateBoard timed out after %zus, continue and "
2539 "there might be racing in content\n",
2540 killing_timeout_sec);
2541 }
2542}
2543
2544static void DoDumpstateBoardAidl(
2545 const std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal,
2546 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2547 const Dumpstate::BugreportMode bugreport_mode, const size_t timeout_sec) {
2548 MYLOGI("Using IDumpstateDevice AIDL HAL");
2549
2550 const char* descriptor_to_kill;
2551 using DumpstateBoardTask = std::packaged_task<bool()>;
2552 DumpstateBoardTask dumpstate_board_task;
2553 dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode dumpstate_hal_mode =
2554 GetDumpstateHalModeAidl(bugreport_mode);
2555
2556 descriptor_to_kill = dumpstate_hal_aidl::IDumpstateDevice::descriptor;
2557 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal, &dumpstate_fds, dumpstate_hal_mode,
2558 timeout_sec]() -> bool {
2559 auto status = dumpstate_hal->dumpstateBoard(dumpstate_fds, dumpstate_hal_mode, timeout_sec);
2560
2561 if (!status.isOk()) {
2562 MYLOGE("dumpstateBoard failed: %s\n", status.getDescription().c_str());
2563 return false;
2564 }
2565 return true;
2566 });
2567 auto result = dumpstate_board_task.get_future();
2568 std::thread(std::move(dumpstate_board_task)).detach();
2569
2570 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2571 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2572 if (!android::base::SetProperty(
2573 "ctl.interface_restart",
2574 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2575 MYLOGE("Couldn't restart dumpstate HAL\n");
2576 }
2577 }
2578 // Wait some time for init to kill dumpstate vendor HAL
2579 constexpr size_t killing_timeout_sec = 10;
2580 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2581 MYLOGE(
2582 "killing dumpstateBoard timed out after %zus, continue and "
2583 "there might be racing in content\n",
2584 killing_timeout_sec);
2585 }
2586}
2587
2588static std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> GetDumpstateBoardAidlService() {
2589 const std::string aidl_instance_name =
2590 std::string(dumpstate_hal_aidl::IDumpstateDevice::descriptor) + "/default";
2591
2592 if (!AServiceManager_isDeclared(aidl_instance_name.c_str())) {
2593 return nullptr;
2594 }
2595
2596 ndk::SpAIBinder dumpstateBinder(AServiceManager_waitForService(aidl_instance_name.c_str()));
2597
2598 return dumpstate_hal_aidl::IDumpstateDevice::fromBinder(dumpstateBinder);
2599}
2600
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002601void Dumpstate::DumpstateBoard(int out_fd) {
2602 dprintf(out_fd, "========================================================\n");
2603 dprintf(out_fd, "== Board\n");
2604 dprintf(out_fd, "========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08002605
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002606 /*
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002607 * mount debugfs for non-user builds with ro.product.debugfs_restrictions.enabled
Hridya Valsaraju51101602021-04-02 14:32:46 -07002608 * set to true and unmount it after invoking dumpstateBoard_* methods.
2609 * This is to enable debug builds to not have debugfs mounted during runtime.
2610 * It will also ensure that debugfs is only accessed by the dumpstate HAL.
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002611 */
Hridya Valsaraju51101602021-04-02 14:32:46 -07002612 auto mount_debugfs =
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002613 android::base::GetBoolProperty("ro.product.debugfs_restrictions.enabled", false);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002614 if (mount_debugfs) {
2615 RunCommand("mount debugfs", {"mount", "-t", "debugfs", "debugfs", "/sys/kernel/debug"},
2616 AS_ROOT_20);
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002617 RunCommand("chmod debugfs", {"chmod", "0755", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002618 }
2619
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002620 std::vector<std::string> paths;
2621 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07002622 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002623 paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
2624 kDumpstateBoardFiles[i].c_str()));
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002625 remover.emplace_back(android::base::make_scope_guard(
2626 std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002627 }
Jie Song9fbfad02017-06-20 16:29:42 -07002628
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002629 // get dumpstate HAL AIDL implementation
2630 std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal_handle_aidl(
2631 GetDumpstateBoardAidlService());
2632 if (dumpstate_hal_handle_aidl == nullptr) {
2633 MYLOGI("No IDumpstateDevice AIDL implementation\n");
2634 }
2635
2636 // get dumpstate HAL HIDL implementation, only if AIDL HAL implementation not found
2637 sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_handle_hidl_1_0 = nullptr;
2638 if (dumpstate_hal_handle_aidl == nullptr) {
2639 dumpstate_hal_handle_hidl_1_0 = dumpstate_hal_hidl_1_0::IDumpstateDevice::getService();
2640 if (dumpstate_hal_handle_hidl_1_0 == nullptr) {
2641 MYLOGI("No IDumpstateDevice HIDL implementation\n");
2642 }
2643 }
2644
2645 // if neither HIDL nor AIDL implementation found, then return
2646 if (dumpstate_hal_handle_hidl_1_0 == nullptr && dumpstate_hal_handle_aidl == nullptr) {
2647 MYLOGE("Could not find IDumpstateDevice implementation\n");
Wei Wang587eac92018-04-05 12:17:20 -07002648 return;
2649 }
2650
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002651 // this is used to hold the file descriptors and when this variable goes out of scope
2652 // the file descriptors are closed
2653 std::vector<::ndk::ScopedFileDescriptor> dumpstate_fds;
Wei Wang587eac92018-04-05 12:17:20 -07002654
Nandana Dutt5c390032019-03-12 10:52:56 +00002655 // TODO(128270426): Check for consent in between?
Wei Wang587eac92018-04-05 12:17:20 -07002656 for (size_t i = 0; i < paths.size(); i++) {
2657 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
2658
2659 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
2660 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
2661 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
2662 if (fd < 0) {
2663 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
2664 return;
2665 }
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002666
2667 dumpstate_fds.emplace_back(fd.release());
2668 // we call fd.release() here to make sure "fd" does not get closed
2669 // after "fd" goes out of scope after this block.
2670 // "fd" will be closed when "dumpstate_fds" goes out of scope
2671 // i.e. when we exit this function
Wei Wang587eac92018-04-05 12:17:20 -07002672 }
2673
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002674 // Given that bugreport is required to diagnose failures, it's better to set an arbitrary amount
2675 // of timeout for IDumpstateDevice than to block the rest of bugreport. In the timeout case, we
2676 // will kill the HAL and grab whatever it dumped in time.
Michael Eastwood8523ea02022-03-10 16:33:08 -08002677 constexpr size_t timeout_sec = 45;
Wei Wang587eac92018-04-05 12:17:20 -07002678
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002679 if (dumpstate_hal_handle_aidl != nullptr) {
2680 DoDumpstateBoardAidl(dumpstate_hal_handle_aidl, dumpstate_fds, options_->bugreport_mode,
2681 timeout_sec);
2682 } else if (dumpstate_hal_handle_hidl_1_0 != nullptr) {
2683 // run HIDL HAL only if AIDL HAL not found
2684 DoDumpstateBoardHidl(dumpstate_hal_handle_hidl_1_0, dumpstate_fds, options_->bugreport_mode,
2685 timeout_sec);
Wei Wang587eac92018-04-05 12:17:20 -07002686 }
2687
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002688 if (mount_debugfs) {
Hridya Valsaraju51101602021-04-02 14:32:46 -07002689 auto keep_debugfs_mounted =
2690 android::base::GetProperty("persist.dbg.keep_debugfs_mounted", "");
2691 if (keep_debugfs_mounted.empty())
2692 RunCommand("unmount debugfs", {"umount", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002693 }
2694
Wei Wang587eac92018-04-05 12:17:20 -07002695 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
2696 for (size_t i = 0; i < paths.size(); i++) {
2697 struct stat s;
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002698 if (fstat(dumpstate_fds[i].get(), &s) == -1) {
2699 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(), strerror(errno));
Wei Wang587eac92018-04-05 12:17:20 -07002700 file_sizes[i] = -1;
2701 continue;
2702 }
2703 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002704 }
2705
2706 for (size_t i = 0; i < paths.size(); i++) {
2707 if (file_sizes[i] == -1) {
2708 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002709 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002710 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07002711 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002712 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002713 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002714 remover[i].Disable();
2715 EnqueueAddZipEntryAndCleanupIfNeeded(kDumpstateBoardFiles[i], paths[i]);
2716 dprintf(out_fd, "*** See %s entry ***\n", kDumpstateBoardFiles[i].c_str());
Jie Song9fbfad02017-06-20 16:29:42 -07002717 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08002718}
2719
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002720static void ShowUsage() {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002721 fprintf(stderr,
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002722 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o directory] [-p] "
2723 "[-s] [-S] [-q] [-P] [-R] [-L] [-V version]\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002724 " -h: display this help message\n"
2725 " -b: play sound file instead of vibrate, at beginning of job\n"
2726 " -e: play sound file instead of vibrate, at end of job\n"
mhasank2d75c442020-06-11 15:05:25 -07002727 " -o: write to custom directory (only in limited mode)\n"
Abhijeet Kaurbb55a3b2019-06-13 18:07:25 +01002728 " -p: capture screenshot to filename.png\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002729 " -s: write zipped file to control socket (for init)\n"
2730 " -S: write file location to control socket (for init)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002731 " -q: disable vibrate\n"
Abhijeet Kaure370d682019-10-01 16:49:30 +01002732 " -P: send broadcast when started and do progress updates\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002733 " -R: take bugreport in remote mode (shouldn't be used with -P)\n"
Nandana Dutt235864b2019-01-22 12:10:16 +00002734 " -w: start binder service and make it wait for a call to startBugreport\n"
mhasankd451a472020-05-26 18:02:39 -07002735 " -L: output limited information that is safe for submission in feedback reports\n"
Felipe Lemed071c682016-10-20 16:48:00 -07002736 " -v: prints the dumpstate header and exit\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002737}
2738
Wei Liuf87959e2016-08-26 14:51:42 -07002739static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07002740 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07002741}
2742
Felipe Leme1d486fe2016-10-14 18:06:47 -07002743bool Dumpstate::FinishZipFile() {
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002744 // Runs all enqueued adding zip entry and cleanup tasks before finishing the zip file.
2745 if (zip_entry_tasks_) {
2746 zip_entry_tasks_->run(/* do_cancel = */false);
2747 }
2748
Felipe Leme9a523ae2016-10-20 15:10:33 -07002749 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07002750 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07002751 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002752 // Final timestamp
2753 char date[80];
2754 time_t the_real_now_please_stand_up = time(nullptr);
2755 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002756 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002757 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002758
Felipe Leme9a523ae2016-10-20 15:10:33 -07002759 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002760 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08002761 return false;
2762 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07002763 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002764 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08002765 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08002766 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08002767
Felipe Leme0f3fb202016-06-10 17:10:53 -07002768 // Add log file (which contains stderr output) to zip...
2769 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002770 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07002771 MYLOGE("Failed to add dumpstate log to .zip file\n");
2772 return false;
2773 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002774 // TODO: Should truncate the existing file.
2775 // ... and re-open it for further logging.
Nandana Dutta344cb62019-02-22 15:12:35 +00002776 if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
2777 return false;
2778 }
Felipe Leme0f3fb202016-06-10 17:10:53 -07002779 fprintf(stderr, "\n");
2780
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002781 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07002782 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002783 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002784 return false;
2785 }
2786
Felipe Leme1d486fe2016-10-14 18:06:47 -07002787 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
2788 ds.zip_file.reset(nullptr);
2789
Felipe Lemee9d2c542016-11-15 11:48:26 -08002790 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002791 android::os::UnlinkAndLogOnError(tmp_path_);
Felipe Lemec4eee562016-04-21 15:42:55 -07002792
Felipe Leme1e9edc62015-12-21 16:02:13 -08002793 return true;
2794}
Felipe Leme6e01fa62015-11-11 19:35:14 -08002795
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00002796static void SendBroadcast(const std::string& action,
2797 const std::vector<std::string>& args,
2798 int32_t user_id) {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002799 // clang-format off
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00002800 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user",
2801 std::to_string(user_id), "--receiver-foreground",
2802 "--receiver-include-background", "-a", action};
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002803 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08002804
2805 am.insert(am.end(), args.begin(), args.end());
2806
Felipe Leme8d2410e2017-02-08 09:46:08 -08002807 RunCommand("", am,
2808 CommandOptions::WithTimeout(20)
2809 .Log("Sending broadcast: '%s'\n")
2810 .Always()
2811 .DropRoot()
2812 .RedirectStderr()
2813 .Build());
2814}
2815
Felipe Leme35b8cf12017-02-10 15:47:29 -08002816static void Vibrate(int duration_ms) {
2817 // clang-format off
Lais Andrade51156962021-02-22 19:21:35 +00002818 std::vector<std::string> args = {"cmd", "vibrator_manager", "synced", "-f", "-d", "dumpstate",
2819 "oneshot", std::to_string(duration_ms)};
2820 RunCommand("", args,
Felipe Leme35b8cf12017-02-10 15:47:29 -08002821 CommandOptions::WithTimeout(10)
2822 .Log("Vibrate: '%s'\n")
2823 .Always()
2824 .Build());
2825 // clang-format on
2826}
2827
Nandana Dutt979388e2018-11-30 16:48:55 +00002828static void MaybeResolveSymlink(std::string* path) {
2829 std::string resolved_path;
2830 if (android::base::Readlink(*path, &resolved_path)) {
2831 *path = resolved_path;
2832 }
2833}
2834
Nandana Dutt4be45d12018-09-26 15:04:23 +01002835/*
2836 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002837 * and adds the version file. Return false if zip_file could not be open to write.
Nandana Dutt4be45d12018-09-26 15:04:23 +01002838 */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002839static bool PrepareToWriteToFile() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002840 MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2841
Nandana Dutt4be45d12018-09-26 15:04:23 +01002842 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2843 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002844 ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002845 char date[80];
2846 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2847 ds.name_ = date;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002848
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002849 if (ds.options_->telephony_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002850 ds.base_name_ += "-telephony";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002851 } else if (ds.options_->wifi_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002852 ds.base_name_ += "-wifi";
2853 }
2854
Paul Chang0d2aad72020-02-13 20:04:03 +08002855 if (ds.options_->do_screenshot) {
Nandana Dutt9d17b942020-03-26 10:02:59 +00002856 ds.screenshot_path_ = ds.GetPath(ds.CalledByApi() ? "-png.tmp" : ".png");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002857 }
2858 ds.tmp_path_ = ds.GetPath(".tmp");
2859 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2860
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01002861 std::string destination = ds.CalledByApi()
Nandana Dutt54dbd672019-01-11 12:58:05 +00002862 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
Nandana Dutt9a76d202019-01-21 15:56:48 +00002863 : ds.bugreport_internal_dir_.c_str();
Nandana Dutt4be45d12018-09-26 15:04:23 +01002864 MYLOGD(
Nandana Dutt235c6672019-11-14 15:22:32 +00002865 "Bugreport dir: [%s] "
2866 "Base name: [%s] "
2867 "Suffix: [%s] "
2868 "Log path: [%s] "
2869 "Temporary path: [%s] "
2870 "Screenshot path: [%s]\n",
Nandana Dutt9a76d202019-01-21 15:56:48 +00002871 destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2872 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002873
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002874 ds.path_ = ds.GetPath(ds.CalledByApi() ? "-zip.tmp" : ".zip");
2875 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2876 create_parent_dirs(ds.path_.c_str());
2877 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2878 if (ds.zip_file == nullptr) {
2879 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2880 return false;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002881 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002882 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2883 ds.AddTextZipEntry("version.txt", ds.version_);
2884 return true;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002885}
2886
2887/*
Abhijeet Kaure370d682019-10-01 16:49:30 +01002888 * Finalizes writing to the file by zipping the tmp file to the final location,
Nandana Dutt4be45d12018-09-26 15:04:23 +01002889 * printing zipped file status, etc.
2890 */
2891static void FinalizeFile() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002892 bool do_text_file = !ds.FinishZipFile();
2893 if (do_text_file) {
2894 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002895 }
mhasank2d75c442020-06-11 15:05:25 -07002896
2897 std::string final_path = ds.path_;
2898 if (ds.options_->OutputToCustomFile()) {
mhasank3a4cfb42020-06-15 18:06:43 -07002899 final_path = ds.GetPath(ds.options_->out_dir, ".zip");
mhasank2d75c442020-06-11 15:05:25 -07002900 android::os::CopyFileToFile(ds.path_, final_path);
2901 }
2902
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002903 if (ds.options_->stream_to_socket) {
2904 android::os::CopyFileToFd(ds.path_, ds.control_socket_fd_);
2905 } else if (ds.options_->progress_updates_to_socket) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002906 if (do_text_file) {
2907 dprintf(ds.control_socket_fd_,
2908 "FAIL:could not create zip file, check %s "
2909 "for more details\n",
2910 ds.log_path_.c_str());
2911 } else {
mhasank2d75c442020-06-11 15:05:25 -07002912 dprintf(ds.control_socket_fd_, "OK:%s\n", final_path.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002913 }
2914 }
2915}
2916
Nandana Dutt4be45d12018-09-26 15:04:23 +01002917
Nandana Dutt58d72e22018-11-16 10:30:48 +00002918static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2919 switch (mode) {
2920 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2921 return "BUGREPORT_FULL";
2922 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2923 return "BUGREPORT_INTERACTIVE";
2924 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2925 return "BUGREPORT_REMOTE";
2926 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2927 return "BUGREPORT_WEAR";
2928 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2929 return "BUGREPORT_TELEPHONY";
2930 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2931 return "BUGREPORT_WIFI";
Elis Elliott8e401ad2023-08-08 11:18:59 +00002932 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
2933 return "BUGREPORT_ONBOARDING";
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002934 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2935 return "BUGREPORT_DEFAULT";
Nandana Dutt58d72e22018-11-16 10:30:48 +00002936 }
2937}
2938
Steven Leeb573eb82022-11-29 22:31:35 +08002939static bool IsConsentlessBugreportAllowed(const Dumpstate::DumpOptions& options) {
2940 // only BUGREPORT_TELEPHONY does not allow using consentless bugreport
2941 return !options.telephony_only;
2942}
2943
Paul Changf59c2b72020-03-10 02:08:55 +08002944static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options,
2945 bool is_screenshot_requested) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002946 // Modify com.android.shell.BugreportProgressService#isDefaultScreenshotRequired as well for
2947 // default system screenshots.
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002948 options->bugreport_mode = mode;
2949 options->bugreport_mode_string = ModeToString(mode);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002950 switch (mode) {
2951 case Dumpstate::BugreportMode::BUGREPORT_FULL:
Paul Changf59c2b72020-03-10 02:08:55 +08002952 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002953 break;
2954 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002955 // Currently, the dumpstate binder is only used by Shell to update progress.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002956 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002957 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002958 break;
2959 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002960 options->do_vibrate = false;
2961 options->is_remote_mode = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002962 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002963 break;
2964 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
Robert Ginda55ecebd2023-04-03 22:53:13 +00002965 options->do_vibrate = false;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002966 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002967 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002968 break;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002969 // TODO(b/148168577) rename TELEPHONY everywhere to CONNECTIVITY.
Nandana Dutt58d72e22018-11-16 10:30:48 +00002970 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002971 options->telephony_only = true;
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002972 options->do_progress_updates = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002973 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002974 break;
2975 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002976 options->wifi_only = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002977 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002978 break;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002979 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
2980 options->onboarding_only = true;
2981 options->do_screenshot = false;
2982 break;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002983 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2984 break;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002985 }
2986}
2987
Nandana Dutt58d72e22018-11-16 10:30:48 +00002988static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
Nandana Dutt235c6672019-11-14 15:22:32 +00002989 MYLOGI(
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002990 "do_vibrate: %d stream_to_socket: %d progress_updates_to_socket: %d do_screenshot: %d "
Rhed Jao25f50e02020-08-20 00:10:32 +08002991 "is_remote_mode: %d show_header_only: %d telephony_only: %d "
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002992 "wifi_only: %d do_progress_updates: %d fd: %d bugreport_mode: %s "
mhasankd451a472020-05-26 18:02:39 -07002993 "limited_only: %d args: %s\n",
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002994 options.do_vibrate, options.stream_to_socket, options.progress_updates_to_socket,
Paul Chang0d2aad72020-02-13 20:04:03 +08002995 options.do_screenshot, options.is_remote_mode, options.show_header_only,
Rhed Jao25f50e02020-08-20 00:10:32 +08002996 options.telephony_only, options.wifi_only,
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002997 options.do_progress_updates, options.bugreport_fd.get(),
2998 options.bugreport_mode_string.c_str(),
2999 options.limited_only, options.args.c_str());
Nandana Dutt58d72e22018-11-16 10:30:48 +00003000}
3001
Nandana Dutt54dbd672019-01-11 12:58:05 +00003002void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
Kean Mariotti306633e2022-09-05 16:30:47 +00003003 int bugreport_flags,
Nandana Dutt54dbd672019-01-11 12:58:05 +00003004 const android::base::unique_fd& bugreport_fd_in,
Paul Changf59c2b72020-03-10 02:08:55 +08003005 const android::base::unique_fd& screenshot_fd_in,
Kholoud Mohameddef4e432024-05-15 12:47:46 +00003006 bool is_screenshot_requested,
3007 bool skip_user_consent) {
Kean Mariotti306633e2022-09-05 16:30:47 +00003008 this->use_predumped_ui_data = bugreport_flags & BugreportFlag::BUGREPORT_USE_PREDUMPED_UI_DATA;
Gavin Corkerya44686c2022-11-23 18:16:51 +00003009 this->is_consent_deferred = bugreport_flags & BugreportFlag::BUGREPORT_FLAG_DEFER_CONSENT;
Kholoud Mohameddef4e432024-05-15 12:47:46 +00003010 this->skip_user_consent = skip_user_consent;
Nandana Dutt54dbd672019-01-11 12:58:05 +00003011 // Duplicate the fds because the passed in fds don't outlive the binder transaction.
Todd Frederick621533f2022-03-26 02:54:17 +00003012 bugreport_fd.reset(fcntl(bugreport_fd_in.get(), F_DUPFD_CLOEXEC, 0));
3013 screenshot_fd.reset(fcntl(screenshot_fd_in.get(), F_DUPFD_CLOEXEC, 0));
Nandana Dutt58d72e22018-11-16 10:30:48 +00003014
Paul Changf59c2b72020-03-10 02:08:55 +08003015 SetOptionsFromMode(bugreport_mode, this, is_screenshot_requested);
Nandana Dutt58d72e22018-11-16 10:30:48 +00003016}
3017
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003018Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
3019 RunStatus status = RunStatus::OK;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003020 int c;
mhasankd451a472020-05-26 18:02:39 -07003021 while ((c = getopt(argc, argv, "dho:svqzpLPBRSV:w")) != -1) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003022 switch (c) {
3023 // clang-format off
mhasank3a4cfb42020-06-15 18:06:43 -07003024 case 'o': out_dir = optarg; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003025 case 's': stream_to_socket = true; break;
3026 case 'S': progress_updates_to_socket = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003027 case 'v': show_header_only = true; break;
3028 case 'q': do_vibrate = false; break;
Paul Chang0d2aad72020-02-13 20:04:03 +08003029 case 'p': do_screenshot = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003030 case 'P': do_progress_updates = true; break;
3031 case 'R': is_remote_mode = true; break;
mhasankd451a472020-05-26 18:02:39 -07003032 case 'L': limited_only = true; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003033 case 'V':
3034 case 'd':
3035 case 'z':
3036 // compatibility no-op
3037 break;
Nandana Dutt235864b2019-01-22 12:10:16 +00003038 case 'w':
3039 // This was already processed
3040 break;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003041 case 'h':
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003042 status = RunStatus::HELP;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003043 break;
3044 default:
3045 fprintf(stderr, "Invalid option: %c\n", c);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003046 status = RunStatus::INVALID_INPUT;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003047 break;
3048 // clang-format on
3049 }
3050 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08003051
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003052 for (int i = 0; i < argc; i++) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003053 args += argv[i];
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003054 if (i < argc - 1) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003055 args += " ";
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003056 }
3057 }
3058
3059 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
3060 optind = 1;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003061
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003062 return status;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003063}
3064
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003065bool Dumpstate::DumpOptions::ValidateOptions() const {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003066 if (bugreport_fd.get() != -1 && stream_to_socket) {
Nandana Dutt979388e2018-11-30 16:48:55 +00003067 return false;
3068 }
3069
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003070 if ((progress_updates_to_socket || do_progress_updates) && stream_to_socket) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003071 return false;
3072 }
3073
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003074 if (is_remote_mode && (do_progress_updates || stream_to_socket)) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003075 return false;
3076 }
3077 return true;
3078}
3079
Nandana Dutt197661d2018-11-16 16:40:21 +00003080void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
3081 options_ = std::move(options);
3082}
3083
Abhijeet Kaura407fb82020-03-27 12:51:12 +00003084void Dumpstate::Initialize() {
3085 /* gets the sequential id */
3086 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
3087 id_ = ++last_id;
3088 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
3089}
3090
Nandana Duttd2f5f082019-01-18 17:13:52 +00003091Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
3092 Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
Gavin Corkerya44686c2022-11-23 18:16:51 +00003093 HandleRunStatus(status);
3094 return status;
3095}
3096
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003097Dumpstate::RunStatus Dumpstate::Retrieve(int32_t calling_uid, const std::string& calling_package,
Kholoud Mohameddef4e432024-05-15 12:47:46 +00003098 const bool keep_bugreport_on_retrieval,
3099 const bool skip_user_consent) {
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003100 Dumpstate::RunStatus status = RetrieveInternal(calling_uid, calling_package,
Kholoud Mohameddef4e432024-05-15 12:47:46 +00003101 keep_bugreport_on_retrieval,
3102 skip_user_consent);
Gavin Corkerya44686c2022-11-23 18:16:51 +00003103 HandleRunStatus(status);
3104 return status;
3105}
3106
3107Dumpstate::RunStatus Dumpstate::RetrieveInternal(int32_t calling_uid,
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003108 const std::string& calling_package,
Kholoud Mohameddef4e432024-05-15 12:47:46 +00003109 const bool keep_bugreport_on_retrieval,
3110 const bool skip_user_consent) {
3111 if (!android::app::admin::flags::onboarding_consentless_bugreports() || !skip_user_consent) {
3112 consent_callback_ = new ConsentCallback();
3113 const String16 incidentcompanion("incidentcompanion");
3114 sp<android::IBinder> ics(
3115 defaultServiceManager()->checkService(incidentcompanion));
3116 android::String16 package(calling_package.c_str());
3117 if (ics != nullptr) {
3118 MYLOGD("Checking user consent via incidentcompanion service\n");
3119
3120 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
3121 calling_uid, package, String16(), String16(),
3122 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
3123 } else {
3124 MYLOGD(
3125 "Unable to check user consent; incidentcompanion service unavailable\n");
3126 return RunStatus::USER_CONSENT_TIMED_OUT;
3127 }
3128 UserConsentResult consent_result = consent_callback_->getResult();
3129 int timeout_ms = 30 * 1000;
3130 while (consent_result == UserConsentResult::UNAVAILABLE &&
3131 consent_callback_->getElapsedTimeMs() < timeout_ms) {
3132 sleep(1);
3133 consent_result = consent_callback_->getResult();
3134 }
3135 if (consent_result == UserConsentResult::DENIED) {
3136 return RunStatus::USER_CONSENT_DENIED;
3137 }
3138 if (consent_result == UserConsentResult::UNAVAILABLE) {
3139 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3140 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3141 consent_callback_.get());
3142 return RunStatus::USER_CONSENT_TIMED_OUT;
3143 }
Gavin Corkerya44686c2022-11-23 18:16:51 +00003144 }
3145
3146 bool copy_succeeded =
3147 android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003148
3149 if (copy_succeeded && (!android::app::admin::flags::onboarding_bugreport_v2_enabled()
3150 || !keep_bugreport_on_retrieval)) {
3151 android::os::UnlinkAndLogOnError(path_);
Gavin Corkerya44686c2022-11-23 18:16:51 +00003152 }
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003153
Gavin Corkerya44686c2022-11-23 18:16:51 +00003154 return copy_succeeded ? Dumpstate::RunStatus::OK
3155 : Dumpstate::RunStatus::ERROR;
3156}
3157
3158void Dumpstate::HandleRunStatus(Dumpstate::RunStatus status) {
3159 if (listener_ != nullptr) {
Nandana Duttbabf6c72019-01-15 14:11:12 +00003160 switch (status) {
3161 case Dumpstate::RunStatus::OK:
Gavin Corkerya44686c2022-11-23 18:16:51 +00003162 listener_->onFinished(path_.c_str());
Nandana Duttbabf6c72019-01-15 14:11:12 +00003163 break;
3164 case Dumpstate::RunStatus::HELP:
3165 break;
3166 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003167 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00003168 break;
3169 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003170 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
3171 break;
3172 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3173 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
3174 break;
3175 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
3176 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00003177 break;
3178 }
3179 }
Nandana Duttbabf6c72019-01-15 14:11:12 +00003180}
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003181void Dumpstate::Cancel() {
3182 CleanupTmpFiles();
3183 android::os::UnlinkAndLogOnError(log_path_);
3184 for (int i = 0; i < NUM_OF_DUMPS; i++) {
3185 android::os::UnlinkAndLogOnError(ds.bugreport_internal_dir_ + "/" +
3186 kDumpstateBoardFiles[i]);
3187 }
3188 tombstone_data_.clear();
3189 anr_data_.clear();
Andy Hungd62f7e62024-01-11 15:47:52 -08003190 anr_trace_data_.clear();
Woody Lin20767a92022-11-29 15:50:24 +08003191 shutdown_checkpoints_.clear();
Rhed Jao0daac912020-08-21 14:48:20 +08003192
3193 // Instead of shutdown the pool, we delete temporary files directly since
3194 // shutdown blocking the call.
3195 if (dump_pool_) {
3196 dump_pool_->deleteTempFiles();
3197 }
3198 if (zip_entry_tasks_) {
3199 zip_entry_tasks_->run(/*do_cancel =*/ true);
3200 }
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003201}
3202
Kean Mariotti306633e2022-09-05 16:30:47 +00003203void Dumpstate::PreDumpUiData() {
Kean Mariottica20f2d2023-12-15 09:34:25 +00003204 auto snapshot_system_trace = MaybeSnapshotSystemTraceAsync();
Kean Mariotti306633e2022-09-05 16:30:47 +00003205 MaybeSnapshotUiTraces();
Kean Mariottica20f2d2023-12-15 09:34:25 +00003206 MaybeWaitForSnapshotSystemTrace(std::move(snapshot_system_trace));
Kean Mariotti306633e2022-09-05 16:30:47 +00003207}
3208
Nandana Dutt979388e2018-11-30 16:48:55 +00003209/*
3210 * Dumps relevant information to a bugreport based on the given options.
3211 *
3212 * The bugreport can be dumped to a file or streamed to a socket.
3213 *
3214 * How dumping to file works:
3215 * stdout is redirected to a temporary file. This will later become the main bugreport entry.
3216 * stderr is redirected a log file.
3217 *
3218 * The temporary bugreport is then populated via printfs, dumping contents of files and
3219 * output of commands to stdout.
3220 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003221 * A bunch of other files and dumps are added to the zip archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00003222 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003223 * The temporary bugreport file and the log file also get added to the archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00003224 *
mhasank2d75c442020-06-11 15:05:25 -07003225 * Bugreports are first generated in a local directory and later copied to the caller's fd
3226 * or directory if supplied.
Nandana Dutt979388e2018-11-30 16:48:55 +00003227 */
Nandana Duttd2f5f082019-01-18 17:13:52 +00003228Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
3229 const std::string& calling_package) {
Rhed Jao5377d792020-07-16 17:37:39 +08003230 DurationReporter duration_reporter("RUN INTERNAL", /* logcat_only = */true);
Nandana Dutt979388e2018-11-30 16:48:55 +00003231 LogDumpOptions(*options_);
Nandana Dutt197661d2018-11-16 16:40:21 +00003232 if (!options_->ValidateOptions()) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00003233 MYLOGE("Invalid options specified\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003234 return RunStatus::INVALID_INPUT;
3235 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003236 /* set as high priority, and protect from OOM killer */
3237 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003238
Felipe Lemed071c682016-10-20 16:48:00 -07003239 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07003240 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003241 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003242 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003243 } else {
3244 /* fallback to kernels <= 2.6.35 */
3245 oom_adj = fopen("/proc/self/oom_adj", "we");
3246 if (oom_adj) {
3247 fputs("-17", oom_adj);
3248 fclose(oom_adj);
3249 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003250 }
3251
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003252 if (version_ == VERSION_DEFAULT) {
3253 version_ = VERSION_CURRENT;
Michal Karpinski4db754f2015-12-11 18:04:32 +00003254 }
3255
Chris Morin5a50d482022-02-01 17:41:18 -08003256 if (version_ != VERSION_CURRENT) {
3257 MYLOGE("invalid version requested ('%s'); supported values are: ('%s', '%s')\n",
3258 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003259 return RunStatus::INVALID_INPUT;
Felipe Lemed071c682016-10-20 16:48:00 -07003260 }
3261
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003262 if (options_->show_header_only) {
3263 PrintHeader();
3264 return RunStatus::OK;
Felipe Lemed071c682016-10-20 16:48:00 -07003265 }
3266
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003267 MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n",
3268 calling_uid, calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003269
Felipe Leme7447d7c2016-11-03 18:12:22 -07003270 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003271 std::string stats_path =
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003272 android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003273 progress_.reset(new Progress(stats_path));
Felipe Leme7447d7c2016-11-03 18:12:22 -07003274
Sahana Raof35ed432019-07-12 10:47:52 +01003275 if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
3276 MYLOGE("Failed to acquire wake lock: %s\n", strerror(errno));
3277 } else {
3278 // Wake lock will be released automatically on process death
3279 MYLOGD("Wake lock acquired.\n");
3280 }
3281
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08003282 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07003283
Felipe Lemef0292972016-11-22 13:57:05 -08003284 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07003285 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
3286 }
3287
Kevin Jeonfa64e642023-07-27 11:36:41 -04003288 if (PropertiesHelper::IsStrictRun()) {
3289 MYLOGI(
3290 "Running on strict-run mode, which has shorter timeouts "
3291 "(to disable, call 'setprop dumpstate.strict_run false')\n");
3292 }
3293
Nandana Dutt235c6672019-11-14 15:22:32 +00003294 MYLOGI("dumpstate info: id=%d, args='%s', bugreport_mode= %s bugreport format version: %s\n",
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00003295 id_, options_->args.c_str(), options_->bugreport_mode_string.c_str(), version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08003296
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003297 do_early_screenshot_ = options_->do_progress_updates;
Felipe Lemee338bf62015-12-07 14:03:50 -08003298
Christopher Ferrised9354f2014-10-01 17:35:01 -07003299 // If we are going to use a socket, do it as early as possible
3300 // to avoid timeouts from bugreport.
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003301 if (options_->stream_to_socket || options_->progress_updates_to_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07003302 MYLOGD("Opening control socket\n");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003303 control_socket_fd_ = open_socket_fn_("dumpstate");
Nandana Dutta344cb62019-02-22 15:12:35 +00003304 if (control_socket_fd_ == -1) {
3305 return ERROR;
3306 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003307 if (options_->progress_updates_to_socket) {
3308 options_->do_progress_updates = 1;
3309 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07003310 }
3311
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003312 if (!PrepareToWriteToFile()) {
3313 return ERROR;
3314 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08003315
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003316 // Interactive, wear & telephony modes are default to true.
3317 // and may enable from cli option or when using control socket
3318 if (options_->do_progress_updates) {
3319 // clang-format off
3320 std::vector<std::string> am_args = {
3321 "--receiver-permission", "android.permission.DUMP",
3322 };
3323 // clang-format on
3324 // Send STARTED broadcast for apps that listen to bugreport generation events
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003325 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED",
3326 am_args, multiuser_get_user_id(calling_uid));
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003327 if (options_->progress_updates_to_socket) {
3328 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08003329 }
3330 }
3331
Nick Kralevichf3599b32016-01-25 15:05:16 -08003332 /* read /proc/cmdline before dropping root */
3333 FILE *cmdline = fopen("/proc/cmdline", "re");
3334 if (cmdline) {
3335 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
3336 fclose(cmdline);
3337 }
3338
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003339 if (options_->do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08003340 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05003341 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003342
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003343 if (zip_file != nullptr) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003344 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
3345 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003346 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08003347 }
3348 }
3349
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003350 int dup_stdout_fd;
3351 int dup_stderr_fd;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003352 // Redirect stderr to log_path_ for debugging.
3353 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
3354 if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
3355 return ERROR;
3356 }
3357 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
3358 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
3359 strerror(errno));
3360 }
Nandana Dutt979388e2018-11-30 16:48:55 +00003361
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003362 // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
3363 // moved into zip file later, if zipping.
3364 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
3365 // TODO: why not write to a file instead of stdout to overcome this problem?
3366 /* TODO: rather than generating a text file now and zipping it later,
3367 it would be more efficient to redirect stdout to the zip entry
3368 directly, but the libziparchive doesn't support that option yet. */
3369 if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
3370 return ERROR;
3371 }
3372 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
3373 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
3374 tmp_path_.c_str(), strerror(errno));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003375 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08003376
3377 // Don't buffer stdout
3378 setvbuf(stdout, nullptr, _IONBF, 0);
3379
Rhed Jao5377d792020-07-16 17:37:39 +08003380 // Enable the parallel run if the client requests to output to a file.
3381 EnableParallelRunIfNeeded();
3382 // Using scope guard to make sure the dump pool can be shut down correctly.
3383 auto scope_guard_to_shutdown_pool = android::base::make_scope_guard([=]() {
3384 ShutdownDumpPool();
3385 });
3386
Felipe Leme608385d2016-02-01 10:35:38 -08003387 // NOTE: there should be no stdout output until now, otherwise it would break the header.
3388 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08003389 // duration is logged into MYLOG instead.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003390 PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003391
Kean Mariottic14cebc2024-03-04 10:55:28 +00003392 bool system_trace_exists = access(SYSTEM_TRACE_SNAPSHOT, F_OK) == 0;
3393 if (options_->use_predumped_ui_data && !system_trace_exists) {
3394 MYLOGW("Ignoring 'use predumped data' flag because no predumped data is available");
3395 options_->use_predumped_ui_data = false;
3396 }
3397
Kean Mariottica20f2d2023-12-15 09:34:25 +00003398 std::future<std::string> snapshot_system_trace;
3399
Kean Mariotti853b73a2023-07-27 12:40:30 +00003400 bool is_dumpstate_restricted =
3401 options_->telephony_only || options_->wifi_only || options_->limited_only;
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003402 if (!is_dumpstate_restricted) {
3403 // Snapshot the system trace now (if running) to avoid that dumpstate's
3404 // own activity pushes out interesting data from the trace ring buffer.
3405 // The trace file is added to the zip by MaybeAddSystemTraceToZip().
Kean Mariottica20f2d2023-12-15 09:34:25 +00003406 snapshot_system_trace = MaybeSnapshotSystemTraceAsync();
Yohei Yukawa95305b32021-03-09 07:54:27 -08003407
Kean Mariotti853b73a2023-07-27 12:40:30 +00003408 // Invoke critical dumpsys to preserve system state, before doing anything else.
3409 RunDumpsysCritical();
3410
Kean Mariotti306633e2022-09-05 16:30:47 +00003411 // Snapshot the UI traces now (if running).
3412 // The trace files will be added to bugreport later.
3413 MaybeSnapshotUiTraces();
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003414 }
Kean Mariotti853b73a2023-07-27 12:40:30 +00003415
3416 MaybeTakeEarlyScreenshot();
Kean Mariottica20f2d2023-12-15 09:34:25 +00003417 MaybeWaitForSnapshotSystemTrace(std::move(snapshot_system_trace));
Gavin Corkery6968f552020-11-22 18:09:05 +00003418 onUiIntensiveBugreportDumpsFinished(calling_uid);
3419 MaybeCheckUserConsent(calling_uid, calling_package);
3420 if (options_->telephony_only) {
3421 DumpstateTelephonyOnly(calling_package);
3422 } else if (options_->wifi_only) {
3423 DumpstateWifiOnly();
3424 } else if (options_->limited_only) {
3425 DumpstateLimitedOnly();
Elis Elliott8e401ad2023-08-08 11:18:59 +00003426 } else if (options_->onboarding_only) {
3427 DumpstateOnboardingOnly();
Gavin Corkery6968f552020-11-22 18:09:05 +00003428 } else {
Nandana Dutt4be45d12018-09-26 15:04:23 +01003429 // Dump state for the default case. This also drops root.
Jichao Lie89d9c12019-11-21 19:02:51 -08003430 RunStatus s = DumpstateDefaultAfterCritical();
Nandana Dutt5c390032019-03-12 10:52:56 +00003431 if (s != RunStatus::OK) {
Nandana Duttaac6f582019-07-26 14:32:47 +01003432 if (s == RunStatus::USER_CONSENT_DENIED) {
Nandana Dutt5c390032019-03-12 10:52:56 +00003433 HandleUserConsentDenied();
3434 }
3435 return s;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08003436 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07003437 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07003438
Felipe Leme55b42a62015-11-10 17:39:08 -08003439 /* close output if needed */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003440 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003441
Abhijeet Kaure370d682019-10-01 16:49:30 +01003442 // Zip the (now complete) .tmp file within the internal directory.
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003443 ATRACE_BEGIN("FinalizeFile");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003444 FinalizeFile();
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003445 ATRACE_END();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003446
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003447 // Share the final file with the caller if the user has consented or Shell is the caller.
Nandana Duttd2f5f082019-01-18 17:13:52 +00003448 Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
Gavin Corkerya44686c2022-11-23 18:16:51 +00003449 if (CalledByApi() && !options_->is_consent_deferred) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003450 status = CopyBugreportIfUserConsented(calling_uid);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003451 if (status != Dumpstate::RunStatus::OK &&
3452 status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3453 // Do an early return if there were errors. We make an exception for consent
3454 // timing out because it's possible the user got distracted. In this case the
3455 // bugreport is not shared but made available for manual retrieval.
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003456 MYLOGI("User denied consent. Returning\n");
Nandana Duttd2f5f082019-01-18 17:13:52 +00003457 return status;
3458 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003459 if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3460 MYLOGI(
3461 "Did not receive user consent yet."
3462 " Will not copy the bugreport artifacts to caller.\n");
Abhijeet Kaur57627412019-04-17 16:00:09 +01003463 const String16 incidentcompanion("incidentcompanion");
3464 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
3465 if (ics != nullptr) {
3466 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3467 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3468 consent_callback_.get());
3469 } else {
3470 MYLOGD("Unable to cancel user consent; incidentcompanion service unavailable\n");
3471 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003472 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003473 }
3474
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003475 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003476 if (options_->do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09003477 for (int i = 0; i < 3; i++) {
3478 Vibrate(75);
3479 usleep((75 + 50) * 1000);
3480 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003481 }
3482
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003483 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
3484 progress_->GetInitialMax());
3485 progress_->Save();
3486 MYLOGI("done (id %d)\n", id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003487
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003488 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08003489
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003490 if (control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07003491 MYLOGD("Closing control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003492 close(control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07003493 }
3494
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003495 tombstone_data_.clear();
3496 anr_data_.clear();
Andy Hungd62f7e62024-01-11 15:47:52 -08003497 anr_trace_data_.clear();
Woody Lin20767a92022-11-29 15:50:24 +08003498 shutdown_checkpoints_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01003499
Nandana Duttd2f5f082019-01-18 17:13:52 +00003500 return (consent_callback_ != nullptr &&
3501 consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
3502 ? USER_CONSENT_TIMED_OUT
3503 : RunStatus::OK;
3504}
3505
Paul Chang0d2aad72020-02-13 20:04:03 +08003506void Dumpstate::MaybeTakeEarlyScreenshot() {
3507 if (!options_->do_screenshot || !do_early_screenshot_) {
3508 return;
3509 }
3510
3511 TakeScreenshot();
3512}
3513
Kean Mariottica20f2d2023-12-15 09:34:25 +00003514std::future<std::string> Dumpstate::MaybeSnapshotSystemTraceAsync() {
Kean Mariotti853b73a2023-07-27 12:40:30 +00003515 // When capturing traces via bugreport handler (BH), this function will be invoked twice:
3516 // 1) When BH invokes IDumpstate::PreDumpUiData()
3517 // 2) When BH invokes IDumpstate::startBugreport(flags = BUGREPORT_USE_PREDUMPED_UI_DATA)
3518 // In this case we don't want to re-invoke perfetto in step 2.
3519 // In all other standard invocation states, this function is invoked once
3520 // without the flag BUGREPORT_USE_PREDUMPED_UI_DATA.
Kean Mariottica20f2d2023-12-15 09:34:25 +00003521 // This function must run asynchronously to avoid delaying MaybeTakeEarlyScreenshot() in the
3522 // standard invocation states (b/316110955).
Kean Mariotti853b73a2023-07-27 12:40:30 +00003523 if (options_->use_predumped_ui_data) {
Kean Mariottica20f2d2023-12-15 09:34:25 +00003524 return {};
3525 }
3526
3527 // Create temporary file for the command's output
3528 std::string outPath = ds.bugreport_internal_dir_ + "/tmp_serialize_perfetto_trace";
3529 auto outFd = android::base::unique_fd(TEMP_FAILURE_RETRY(
3530 open(outPath.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
3531 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
3532 if (outFd < 0) {
3533 MYLOGE("Could not open %s to serialize perfetto trace.\n", outPath.c_str());
3534 return {};
Kean Mariotti853b73a2023-07-27 12:40:30 +00003535 }
3536
3537 // If a stale file exists already, remove it.
3538 unlink(SYSTEM_TRACE_SNAPSHOT);
3539
Kean Mariottica20f2d2023-12-15 09:34:25 +00003540 MYLOGI("Launching async '%s'", SERIALIZE_PERFETTO_TRACE_TASK.c_str())
3541 return std::async(
3542 std::launch::async, [this, outPath = std::move(outPath), outFd = std::move(outFd)] {
3543 // If a background system trace is happening and is marked as "suitable for
3544 // bugreport" (i.e. bugreport_score > 0 in the trace config), this command
3545 // will stop it and serialize into SYSTEM_TRACE_SNAPSHOT. In the (likely)
3546 // case that no trace is ongoing, this command is a no-op.
3547 // Note: this should not be enqueued as we need to freeze the trace before
3548 // dumpstate starts. Otherwise the trace ring buffers will contain mostly
3549 // the dumpstate's own activity which is irrelevant.
3550 RunCommand(
3551 SERIALIZE_PERFETTO_TRACE_TASK, {"perfetto", "--save-for-bugreport"},
3552 CommandOptions::WithTimeout(10).DropRoot().CloseAllFileDescriptorsOnExec().Build(),
3553 false, outFd);
3554 // MaybeAddSystemTraceToZip() will take care of copying the trace in the zip
3555 // file in the later stages.
3556
3557 return outPath;
3558 });
3559}
3560
3561void Dumpstate::MaybeWaitForSnapshotSystemTrace(std::future<std::string> task) {
3562 if (!task.valid()) {
3563 return;
3564 }
3565
3566 WaitForTask(std::move(task), SERIALIZE_PERFETTO_TRACE_TASK, STDOUT_FILENO);
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003567}
3568
Kean Mariotti306633e2022-09-05 16:30:47 +00003569void Dumpstate::MaybeSnapshotUiTraces() {
3570 if (PropertiesHelper::IsUserBuild() || options_->use_predumped_ui_data) {
3571 return;
3572 }
3573
Pablo Gamito654831c2024-02-16 16:47:48 +00003574 std::vector<std::vector<std::string>> dumpTracesForBugReportCommands = {
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003575 {"cmd", "input_method", "tracing", "save-for-bugreport"},
3576 {"cmd", "window", "tracing", "save-for-bugreport"},
3577 {"cmd", "window", "shell", "tracing", "save-for-bugreport"},
3578 };
Hongwei Wang39229132023-01-24 15:09:59 -08003579
Pablo Gamito654831c2024-02-16 16:47:48 +00003580 if (!android_tracing_perfetto_transition_tracing()) {
3581 dumpTracesForBugReportCommands.push_back({"dumpsys", "activity", "service",
3582 "SystemUIService", "WMShell", "transitions",
3583 "tracing", "save-for-bugreport"});
3584 }
3585
Pablo Gamito6929a0e2024-02-26 23:29:47 +00003586 if (!android_tracing_perfetto_protolog_tracing()) {
Pablo Gamito654831c2024-02-16 16:47:48 +00003587 dumpTracesForBugReportCommands.push_back({"dumpsys", "activity", "service",
3588 "SystemUIService", "WMShell", "protolog",
3589 "save-for-bugreport"});
3590 }
3591
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003592 for (const auto& command : dumpTracesForBugReportCommands) {
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003593 RunCommand(
3594 // Empty name because it's not intended to be classified as a bugreport section.
3595 // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003596 "", command,
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003597 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
3598 }
Kean Mariotti306633e2022-09-05 16:30:47 +00003599}
3600
3601void Dumpstate::MaybeAddUiTracesToZip() {
3602 if (PropertiesHelper::IsUserBuild()) {
3603 return;
3604 }
3605
3606 ds.AddDir(WMTRACE_DATA_DIR, false);
Yohei Yukawa95305b32021-03-09 07:54:27 -08003607}
3608
Paul Changeb4b4642020-05-28 22:05:47 +08003609void Dumpstate::onUiIntensiveBugreportDumpsFinished(int32_t calling_uid) {
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003610 if (multiuser_get_app_id(calling_uid) == AID_SHELL || !CalledByApi()) {
Paul Changc490e662020-04-11 18:14:09 +08003611 return;
3612 }
3613 if (listener_ != nullptr) {
3614 // Let listener know ui intensive bugreport dumps are finished, then it can do event
3615 // handling if required.
Paul Changeb4b4642020-05-28 22:05:47 +08003616 listener_->onUiIntensiveBugreportDumpsFinished();
Paul Changc490e662020-04-11 18:14:09 +08003617 }
3618}
3619
Jichao Lie89d9c12019-11-21 19:02:51 -08003620void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) {
Gavin Corkerya44686c2022-11-23 18:16:51 +00003621 if (multiuser_get_app_id(calling_uid) == AID_SHELL ||
Kholoud Mohameddef4e432024-05-15 12:47:46 +00003622 !CalledByApi() || options_->is_consent_deferred ||
3623 (android::app::admin::flags::onboarding_consentless_bugreports() &&
3624 options_->skip_user_consent)) {
Gavin Corkerya44686c2022-11-23 18:16:51 +00003625 // No need to get consent for shell triggered dumpstates, or not
3626 // through bugreporting API (i.e. no fd to copy back), or when consent
3627 // is deferred.
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003628 return;
3629 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003630 consent_callback_ = new ConsentCallback();
3631 const String16 incidentcompanion("incidentcompanion");
3632 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
Jichao Lie89d9c12019-11-21 19:02:51 -08003633 android::String16 package(calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003634 if (ics != nullptr) {
3635 MYLOGD("Checking user consent via incidentcompanion service\n");
Steven Leeb573eb82022-11-29 22:31:35 +08003636 int flags = 0x1; // IncidentManager.FLAG_CONFIRMATION_DIALOG
3637 if (IsConsentlessBugreportAllowed(*options_)) {
3638 flags |= 0x2; // IncidentManager.FLAG_ALLOW_CONSENTLESS_BUGREPORT
3639 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003640 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
Steven Leeb573eb82022-11-29 22:31:35 +08003641 calling_uid, package, String16(), String16(), flags, consent_callback_.get());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003642 } else {
3643 MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
3644 }
3645}
3646
Nandana Dutt5c390032019-03-12 10:52:56 +00003647bool Dumpstate::IsUserConsentDenied() const {
3648 return ds.consent_callback_ != nullptr &&
3649 ds.consent_callback_->getResult() == UserConsentResult::DENIED;
3650}
3651
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01003652bool Dumpstate::CalledByApi() const {
3653 return ds.options_->bugreport_fd.get() != -1 ? true : false;
3654}
3655
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003656void Dumpstate::CleanupTmpFiles() {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003657 android::os::UnlinkAndLogOnError(tmp_path_);
3658 android::os::UnlinkAndLogOnError(screenshot_path_);
3659 android::os::UnlinkAndLogOnError(path_);
Gavin Corkery789d7a52021-02-24 23:52:35 +00003660 if (dump_traces_path != nullptr) {
3661 android::os::UnlinkAndLogOnError(dump_traces_path);
3662 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003663}
3664
Rhed Jao5377d792020-07-16 17:37:39 +08003665void Dumpstate::EnableParallelRunIfNeeded() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003666 if (!PropertiesHelper::IsParallelRun()) {
Rhed Jao5377d792020-07-16 17:37:39 +08003667 return;
3668 }
3669 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003670 zip_entry_tasks_ = std::make_unique<TaskQueue>();
Rhed Jao5377d792020-07-16 17:37:39 +08003671}
3672
3673void Dumpstate::ShutdownDumpPool() {
3674 if (dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08003675 dump_pool_.reset();
Rhed Jao5377d792020-07-16 17:37:39 +08003676 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003677 if (zip_entry_tasks_) {
3678 zip_entry_tasks_->run(/* do_cancel = */true);
3679 zip_entry_tasks_ = nullptr;
3680 }
3681}
3682
3683void Dumpstate::EnqueueAddZipEntryAndCleanupIfNeeded(const std::string& entry_name,
3684 const std::string& entry_path) {
3685 auto func_add_zip_entry_and_cleanup = [=](bool task_cancelled) {
3686 if (!task_cancelled) {
3687 AddZipEntry(entry_name, entry_path);
3688 }
3689 android::os::UnlinkAndLogOnError(entry_path);
3690 };
3691 if (zip_entry_tasks_) {
3692 // Enqueues AddZipEntryAndCleanup function if the parallel run is enabled.
3693 zip_entry_tasks_->add(func_add_zip_entry_and_cleanup, _1);
3694 } else {
3695 // Invokes AddZipEntryAndCleanup immediately
3696 std::invoke(func_add_zip_entry_and_cleanup, /* task_cancelled = */false);
3697 }
Rhed Jao5377d792020-07-16 17:37:39 +08003698}
3699
Nandana Duttd2f5f082019-01-18 17:13:52 +00003700Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
3701 MYLOGD("User denied consent; deleting files and returning\n");
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003702 CleanupTmpFiles();
Nandana Duttd2f5f082019-01-18 17:13:52 +00003703 return USER_CONSENT_DENIED;
3704}
3705
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003706Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented(int32_t calling_uid) {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003707 // If the caller has asked to copy the bugreport over to their directory, we need explicit
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003708 // user consent (unless the caller is Shell).
3709 UserConsentResult consent_result;
Kholoud Mohameddef4e432024-05-15 12:47:46 +00003710 if (multiuser_get_app_id(calling_uid) == AID_SHELL || (options_->skip_user_consent
3711 && android::app::admin::flags::onboarding_consentless_bugreports())) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003712 consent_result = UserConsentResult::APPROVED;
3713 } else {
3714 consent_result = consent_callback_->getResult();
3715 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003716 if (consent_result == UserConsentResult::UNAVAILABLE) {
3717 // User has not responded yet.
3718 uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
Hunter Knepshield70610fa2020-01-03 15:27:33 -08003719 // Telephony is a fast report type, particularly on user builds where information may be
3720 // more aggressively limited. To give the user time to read the consent dialog, increase the
3721 // timeout.
3722 uint64_t timeout_ms = options_->telephony_only ? TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS
3723 : USER_CONSENT_TIMEOUT_MS;
3724 if (elapsed_ms < timeout_ms) {
3725 uint delay_seconds = (timeout_ms - elapsed_ms) / 1000;
Nandana Duttd2f5f082019-01-18 17:13:52 +00003726 MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
3727 sleep(delay_seconds);
3728 }
3729 consent_result = consent_callback_->getResult();
3730 }
3731 if (consent_result == UserConsentResult::DENIED) {
3732 // User has explicitly denied sharing with the app. To be safe delete the
3733 // internal bugreport & tmp files.
3734 return HandleUserConsentDenied();
3735 }
3736 if (consent_result == UserConsentResult::APPROVED) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00003737 bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
3738 if (copy_succeeded) {
3739 android::os::UnlinkAndLogOnError(path_);
Abhijeet Kaur9ce94672020-04-01 17:22:36 +01003740 if (options_->do_screenshot &&
3741 options_->screenshot_fd.get() != -1 &&
3742 !options_->is_screenshot_copied) {
3743 copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
3744 options_->screenshot_fd.get());
3745 options_->is_screenshot_copied = copy_succeeded;
3746 if (copy_succeeded) {
3747 android::os::UnlinkAndLogOnError(screenshot_path_);
3748 }
3749 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003750 }
3751 return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
3752 } else if (consent_result == UserConsentResult::UNAVAILABLE) {
3753 // consent_result is still UNAVAILABLE. The user has likely not responded yet.
3754 // Since we do not have user consent to share the bugreport it does not get
3755 // copied over to the calling app but remains in the internal directory from
3756 // where the user can manually pull it.
Paul Changce644212021-05-11 16:06:45 +08003757 std::string final_path = GetPath(".zip");
3758 bool copy_succeeded = android::os::CopyFileToFile(path_, final_path);
3759 if (copy_succeeded) {
3760 android::os::UnlinkAndLogOnError(path_);
3761 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003762 return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
3763 }
3764 // Unknown result; must be a programming error.
3765 MYLOGE("Unknown user consent result:%d\n", consent_result);
3766 return Dumpstate::RunStatus::ERROR;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003767}
3768
Nandana Duttf02564e2019-02-15 15:24:24 +00003769Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003770 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
3771 Dumpstate::RunStatus status = options->Initialize(argc, argv);
3772 if (status == Dumpstate::RunStatus::OK) {
Nandana Duttf02564e2019-02-15 15:24:24 +00003773 SetOptions(std::move(options));
Nandana Duttd2f5f082019-01-18 17:13:52 +00003774 // When directly running dumpstate binary, the output is not expected to be written
3775 // to any external file descriptor.
Nandana Duttf02564e2019-02-15 15:24:24 +00003776 assert(options_->bugreport_fd.get() == -1);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003777
3778 // calling_uid and calling_package are for user consent to share the bugreport with
Abhijeet Kaura407fb82020-03-27 12:51:12 +00003779 // an app; they are irrelevant here because bugreport is triggered via command line.
3780 // Update Last ID before calling Run().
3781 Initialize();
Nikhil Kumarb70622a2023-06-15 15:37:19 +01003782 status = Run(0 /* calling_uid */, "" /* calling_package */);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003783 }
Nandana Duttf02564e2019-02-15 15:24:24 +00003784 return status;
3785}
3786
3787/* Main entry point for dumpstate binary. */
3788int run_main(int argc, char* argv[]) {
3789 Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003790
3791 switch (status) {
3792 case Dumpstate::RunStatus::OK:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003793 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003794 case Dumpstate::RunStatus::HELP:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003795 ShowUsage();
3796 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003797 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003798 fprintf(stderr, "Invalid combination of args\n");
3799 ShowUsage();
3800 exit(1);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003801 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003802 FALLTHROUGH_INTENDED;
3803 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3804 FALLTHROUGH_INTENDED;
3805 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003806 exit(2);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003807 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003808}
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003809
3810// TODO(111441001): Default DumpOptions to sensible values.
3811Dumpstate::Dumpstate(const std::string& version)
3812 : pid_(getpid()),
3813 options_(new Dumpstate::DumpOptions()),
Nandana Dutt402a8392019-06-14 14:25:13 +01003814 last_reported_percent_progress_(0),
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003815 version_(version),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003816 now_(time(nullptr)),
3817 open_socket_fn_(open_socket) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003818}
3819
3820Dumpstate& Dumpstate::GetInstance() {
3821 static Dumpstate singleton_(android::base::GetProperty("dumpstate.version", VERSION_CURRENT));
3822 return singleton_;
3823}
3824
Rhed Jao5377d792020-07-16 17:37:39 +08003825DurationReporter::DurationReporter(const std::string& title, bool logcat_only, bool verbose,
3826 int duration_fd) : title_(title), logcat_only_(logcat_only), verbose_(verbose),
3827 duration_fd_(duration_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003828 if (!title_.empty()) {
3829 started_ = Nanotime();
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003830 if (title_.find("SHOW MAP") == std::string::npos) {
3831 ATRACE_ASYNC_BEGIN(title_.c_str(), 0);
3832 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003833 }
3834}
3835
3836DurationReporter::~DurationReporter() {
3837 if (!title_.empty()) {
3838 float elapsed = (float)(Nanotime() - started_) / NANOS_PER_SEC;
chenqiwuaf8b2d92019-12-12 18:53:51 +08003839 if (elapsed >= .5f || verbose_) {
3840 MYLOGD("Duration of '%s': %.2fs\n", title_.c_str(), elapsed);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003841 }
chenqiwuaf8b2d92019-12-12 18:53:51 +08003842 if (!logcat_only_) {
3843 // Use "Yoda grammar" to make it easier to grep|sort sections.
Rhed Jao5377d792020-07-16 17:37:39 +08003844 dprintf(duration_fd_, "------ %.3fs was the duration of '%s' ------\n",
3845 elapsed, title_.c_str());
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003846 }
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003847 if (title_.find("SHOW MAP") == std::string::npos) {
3848 ATRACE_ASYNC_END(title_.c_str(), 0);
3849 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003850 }
3851}
3852
3853const int32_t Progress::kDefaultMax = 5000;
3854
3855Progress::Progress(const std::string& path) : Progress(Progress::kDefaultMax, 1.1, path) {
3856}
3857
3858Progress::Progress(int32_t initial_max, int32_t progress, float growth_factor)
3859 : Progress(initial_max, growth_factor, "") {
3860 progress_ = progress;
3861}
3862
3863Progress::Progress(int32_t initial_max, float growth_factor, const std::string& path)
3864 : initial_max_(initial_max),
3865 progress_(0),
3866 max_(initial_max),
3867 growth_factor_(growth_factor),
3868 n_runs_(0),
3869 average_max_(0),
3870 path_(path) {
3871 if (!path_.empty()) {
3872 Load();
3873 }
3874}
3875
3876void Progress::Load() {
3877 MYLOGD("Loading stats from %s\n", path_.c_str());
3878 std::string content;
3879 if (!android::base::ReadFileToString(path_, &content)) {
3880 MYLOGI("Could not read stats from %s; using max of %d\n", path_.c_str(), max_);
3881 return;
3882 }
3883 if (content.empty()) {
3884 MYLOGE("No stats (empty file) on %s; using max of %d\n", path_.c_str(), max_);
3885 return;
3886 }
3887 std::vector<std::string> lines = android::base::Split(content, "\n");
3888
3889 if (lines.size() < 1) {
3890 MYLOGE("Invalid stats on file %s: not enough lines (%d). Using max of %d\n", path_.c_str(),
3891 (int)lines.size(), max_);
3892 return;
3893 }
3894 char* ptr;
3895 n_runs_ = strtol(lines[0].c_str(), &ptr, 10);
3896 average_max_ = strtol(ptr, nullptr, 10);
3897 if (n_runs_ <= 0 || average_max_ <= 0 || n_runs_ > STATS_MAX_N_RUNS ||
3898 average_max_ > STATS_MAX_AVERAGE) {
3899 MYLOGE("Invalid stats line on file %s: %s\n", path_.c_str(), lines[0].c_str());
3900 initial_max_ = Progress::kDefaultMax;
3901 } else {
3902 initial_max_ = average_max_;
3903 }
3904 max_ = initial_max_;
3905
3906 MYLOGI("Average max progress: %d in %d runs; estimated max: %d\n", average_max_, n_runs_, max_);
3907}
3908
3909void Progress::Save() {
3910 int32_t total = n_runs_ * average_max_ + progress_;
3911 int32_t runs = n_runs_ + 1;
3912 int32_t average = floor(((float)total) / runs);
3913 MYLOGI("Saving stats (total=%d, runs=%d, average=%d) on %s\n", total, runs, average,
3914 path_.c_str());
3915 if (path_.empty()) {
3916 return;
3917 }
3918
3919 std::string content = android::base::StringPrintf("%d %d\n", runs, average);
3920 if (!android::base::WriteStringToFile(content, path_)) {
3921 MYLOGE("Could not save stats on %s\n", path_.c_str());
3922 }
3923}
3924
3925int32_t Progress::Get() const {
3926 return progress_;
3927}
3928
3929bool Progress::Inc(int32_t delta_sec) {
3930 bool changed = false;
3931 if (delta_sec >= 0) {
3932 progress_ += delta_sec;
3933 if (progress_ > max_) {
3934 int32_t old_max = max_;
3935 max_ = floor((float)progress_ * growth_factor_);
3936 MYLOGD("Adjusting max progress from %d to %d\n", old_max, max_);
3937 changed = true;
3938 }
3939 }
3940 return changed;
3941}
3942
3943int32_t Progress::GetMax() const {
3944 return max_;
3945}
3946
3947int32_t Progress::GetInitialMax() const {
3948 return initial_max_;
3949}
3950
3951void Progress::Dump(int fd, const std::string& prefix) const {
3952 const char* pr = prefix.c_str();
3953 dprintf(fd, "%sprogress: %d\n", pr, progress_);
3954 dprintf(fd, "%smax: %d\n", pr, max_);
3955 dprintf(fd, "%sinitial_max: %d\n", pr, initial_max_);
3956 dprintf(fd, "%sgrowth_factor: %0.2f\n", pr, growth_factor_);
3957 dprintf(fd, "%spath: %s\n", pr, path_.c_str());
3958 dprintf(fd, "%sn_runs: %d\n", pr, n_runs_);
3959 dprintf(fd, "%saverage_max: %d\n", pr, average_max_);
3960}
3961
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003962std::string Dumpstate::GetPath(const std::string& suffix) const {
3963 return GetPath(bugreport_internal_dir_, suffix);
3964}
3965
3966std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
3967 return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
3968 name_.c_str(), suffix.c_str());
3969}
3970
3971void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
3972 progress_ = std::move(progress);
3973}
3974
3975void for_each_userid(void (*func)(int), const char *header) {
3976 std::string title = header == nullptr ? "for_each_userid" : android::base::StringPrintf(
3977 "for_each_userid(%s)", header);
3978 DurationReporter duration_reporter(title);
3979 if (PropertiesHelper::IsDryRun()) return;
3980
3981 DIR *d;
3982 struct dirent *de;
3983
3984 if (header) printf("\n------ %s ------\n", header);
3985 func(0);
3986
3987 if (!(d = opendir("/data/system/users"))) {
3988 printf("Failed to open /data/system/users (%s)\n", strerror(errno));
3989 return;
3990 }
3991
3992 while ((de = readdir(d))) {
3993 int userid;
3994 if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
3995 continue;
3996 }
3997 func(userid);
3998 }
3999
4000 closedir(d);
4001}
4002
4003static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
4004 DIR *d;
4005 struct dirent *de;
4006
4007 if (!(d = opendir("/proc"))) {
4008 printf("Failed to open /proc (%s)\n", strerror(errno));
4009 return;
4010 }
4011
4012 if (header) printf("\n------ %s ------\n", header);
4013 while ((de = readdir(d))) {
4014 if (ds.IsUserConsentDenied()) {
4015 MYLOGE(
4016 "Returning early because user denied consent to share bugreport with calling app.");
4017 closedir(d);
4018 return;
4019 }
4020 int pid;
4021 int fd;
4022 char cmdpath[255];
4023 char cmdline[255];
4024
4025 if (!(pid = atoi(de->d_name))) {
4026 continue;
4027 }
4028
4029 memset(cmdline, 0, sizeof(cmdline));
4030
4031 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
4032 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
4033 TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
4034 close(fd);
4035 if (cmdline[0]) {
4036 helper(pid, cmdline, arg);
4037 continue;
4038 }
4039 }
4040
4041 // if no cmdline, a kernel thread has comm
4042 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
4043 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
4044 TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
4045 close(fd);
4046 if (cmdline[1]) {
4047 cmdline[0] = '[';
4048 size_t len = strcspn(cmdline, "\f\b\r\n");
4049 cmdline[len] = ']';
4050 cmdline[len+1] = '\0';
4051 }
4052 }
4053 if (!cmdline[0]) {
4054 strcpy(cmdline, "N/A");
4055 }
4056 helper(pid, cmdline, arg);
4057 }
4058
4059 closedir(d);
4060}
4061
4062static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
4063 for_each_pid_func *func = (for_each_pid_func*) arg;
4064 func(pid, cmdline);
4065}
4066
4067void for_each_pid(for_each_pid_func func, const char *header) {
4068 std::string title = header == nullptr ? "for_each_pid"
4069 : android::base::StringPrintf("for_each_pid(%s)", header);
4070 DurationReporter duration_reporter(title);
4071 if (PropertiesHelper::IsDryRun()) return;
4072
4073 __for_each_pid(for_each_pid_helper, header, (void *) func);
4074}
4075
4076static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
4077 DIR *d;
4078 struct dirent *de;
4079 char taskpath[255];
4080 for_each_tid_func *func = (for_each_tid_func *) arg;
4081
4082 snprintf(taskpath, sizeof(taskpath), "/proc/%d/task", pid);
4083
4084 if (!(d = opendir(taskpath))) {
4085 printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
4086 return;
4087 }
4088
4089 func(pid, pid, cmdline);
4090
4091 while ((de = readdir(d))) {
4092 if (ds.IsUserConsentDenied()) {
4093 MYLOGE(
4094 "Returning early because user denied consent to share bugreport with calling app.");
4095 closedir(d);
4096 return;
4097 }
4098 int tid;
4099 int fd;
4100 char commpath[255];
4101 char comm[255];
4102
4103 if (!(tid = atoi(de->d_name))) {
4104 continue;
4105 }
4106
4107 if (tid == pid)
4108 continue;
4109
4110 snprintf(commpath, sizeof(commpath), "/proc/%d/comm", tid);
4111 memset(comm, 0, sizeof(comm));
4112 if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
4113 strcpy(comm, "N/A");
4114 } else {
4115 char *c;
4116 TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
4117 close(fd);
4118
4119 c = strrchr(comm, '\n');
4120 if (c) {
4121 *c = '\0';
4122 }
4123 }
4124 func(pid, tid, comm);
4125 }
4126
4127 closedir(d);
4128}
4129
4130void for_each_tid(for_each_tid_func func, const char *header) {
4131 std::string title = header == nullptr ? "for_each_tid"
4132 : android::base::StringPrintf("for_each_tid(%s)", header);
4133 DurationReporter duration_reporter(title);
4134
4135 if (PropertiesHelper::IsDryRun()) return;
4136
4137 __for_each_pid(for_each_tid_helper, header, (void *) func);
4138}
4139
4140void show_wchan(int pid, int tid, const char *name) {
4141 if (PropertiesHelper::IsDryRun()) return;
4142
4143 char path[255];
4144 char buffer[255];
4145 int fd, ret, save_errno;
4146 char name_buffer[255];
4147
4148 memset(buffer, 0, sizeof(buffer));
4149
4150 snprintf(path, sizeof(path), "/proc/%d/wchan", tid);
4151 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
4152 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
4153 return;
4154 }
4155
4156 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
4157 save_errno = errno;
4158 close(fd);
4159
4160 if (ret < 0) {
4161 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
4162 return;
4163 }
4164
4165 snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
4166 pid == tid ? 0 : 3, "", name);
4167
4168 printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
4169
4170 return;
4171}
4172
4173// print time in centiseconds
4174static void snprcent(char *buffer, size_t len, size_t spc,
4175 unsigned long long time) {
4176 static long hz; // cache discovered hz
4177
4178 if (hz <= 0) {
4179 hz = sysconf(_SC_CLK_TCK);
4180 if (hz <= 0) {
4181 hz = 1000;
4182 }
4183 }
4184
4185 // convert to centiseconds
4186 time = (time * 100 + (hz / 2)) / hz;
4187
4188 char str[16];
4189
4190 snprintf(str, sizeof(str), " %llu.%02u",
4191 time / 100, (unsigned)(time % 100));
4192 size_t offset = strlen(buffer);
4193 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
4194 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
4195}
4196
4197// print permille as a percent
4198static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
4199 char str[16];
4200
4201 snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
4202 size_t offset = strlen(buffer);
4203 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
4204 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
4205}
4206
4207void show_showtime(int pid, const char *name) {
4208 if (PropertiesHelper::IsDryRun()) return;
4209
4210 char path[255];
4211 char buffer[1023];
4212 int fd, ret, save_errno;
4213
4214 memset(buffer, 0, sizeof(buffer));
4215
4216 snprintf(path, sizeof(path), "/proc/%d/stat", pid);
4217 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
4218 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
4219 return;
4220 }
4221
4222 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
4223 save_errno = errno;
4224 close(fd);
4225
4226 if (ret < 0) {
4227 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
4228 return;
4229 }
4230
4231 // field 14 is utime
4232 // field 15 is stime
4233 // field 42 is iotime
4234 unsigned long long utime = 0, stime = 0, iotime = 0;
4235 if (sscanf(buffer,
4236 "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
4237 "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
4238 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
4239 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
4240 &utime, &stime, &iotime) != 3) {
4241 return;
4242 }
4243
4244 unsigned long long total = utime + stime;
4245 if (!total) {
4246 return;
4247 }
4248
4249 unsigned permille = (iotime * 1000 + (total / 2)) / total;
4250 if (permille > 1000) {
4251 permille = 1000;
4252 }
4253
4254 // try to beautify and stabilize columns at <80 characters
4255 snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
4256 if ((name[0] != '[') || utime) {
4257 snprcent(buffer, sizeof(buffer), 57, utime);
4258 }
4259 snprcent(buffer, sizeof(buffer), 65, stime);
4260 if ((name[0] != '[') || iotime) {
4261 snprcent(buffer, sizeof(buffer), 73, iotime);
4262 }
4263 if (iotime) {
4264 snprdec(buffer, sizeof(buffer), 79, permille);
4265 }
4266 puts(buffer); // adds a trailing newline
4267
4268 return;
4269}
4270
4271void do_dmesg() {
4272 const char *title = "KERNEL LOG (dmesg)";
4273 DurationReporter duration_reporter(title);
4274 printf("------ %s ------\n", title);
4275
4276 if (PropertiesHelper::IsDryRun()) return;
4277
4278 /* Get size of kernel buffer */
4279 int size = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
4280 if (size <= 0) {
4281 printf("Unexpected klogctl return value: %d\n\n", size);
4282 return;
4283 }
4284 char *buf = (char *) malloc(size + 1);
4285 if (buf == nullptr) {
4286 printf("memory allocation failed\n\n");
4287 return;
4288 }
4289 int retval = klogctl(KLOG_READ_ALL, buf, size);
4290 if (retval < 0) {
4291 printf("klogctl failure\n\n");
4292 free(buf);
4293 return;
4294 }
4295 buf[retval] = '\0';
4296 printf("%s\n\n", buf);
4297 free(buf);
4298 return;
4299}
4300
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004301int Dumpstate::DumpFile(const std::string& title, const std::string& path) {
4302 DurationReporter duration_reporter(title);
4303
4304 int status = DumpFileToFd(STDOUT_FILENO, title, path);
4305
4306 UpdateProgress(WEIGHT_FILE);
4307
4308 return status;
4309}
4310
4311int read_file_as_long(const char *path, long int *output) {
luoqiangwei15fcf2022024-03-07 15:29:20 +08004312 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
4313 if (fd.get() < 0) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004314 int err = errno;
4315 MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
4316 return -1;
4317 }
4318 char buffer[50];
luoqiangwei15fcf2022024-03-07 15:29:20 +08004319 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer, sizeof(buffer)));
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004320 if (bytes_read == -1) {
4321 MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
4322 return -2;
4323 }
4324 if (bytes_read == 0) {
4325 MYLOGE("File %s is empty\n", path);
4326 return -3;
4327 }
4328 *output = atoi(buffer);
4329 return 0;
4330}
4331
4332/* calls skip to gate calling dump_from_fd recursively
4333 * in the specified directory. dump_from_fd defaults to
4334 * dump_file_from_fd above when set to NULL. skip defaults
4335 * to false when set to NULL. dump_from_fd will always be
4336 * called with title NULL.
4337 */
4338int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
4339 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4340 DurationReporter duration_reporter(title);
4341 DIR *dirp;
4342 struct dirent *d;
4343 char *newpath = nullptr;
4344 const char *slash = "/";
4345 int retval = 0;
4346
4347 if (!title.empty()) {
4348 printf("------ %s (%s) ------\n", title.c_str(), dir);
4349 }
4350 if (PropertiesHelper::IsDryRun()) return 0;
4351
4352 if (dir[strlen(dir) - 1] == '/') {
4353 ++slash;
4354 }
4355 dirp = opendir(dir);
4356 if (dirp == nullptr) {
4357 retval = -errno;
4358 MYLOGE("%s: %s\n", dir, strerror(errno));
4359 return retval;
4360 }
4361
4362 if (!dump_from_fd) {
4363 dump_from_fd = dump_file_from_fd;
4364 }
4365 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4366 if ((d->d_name[0] == '.')
4367 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4368 || (d->d_name[1] == '\0'))) {
4369 continue;
4370 }
4371 asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
4372 (d->d_type == DT_DIR) ? "/" : "");
4373 if (!newpath) {
4374 retval = -errno;
4375 continue;
4376 }
4377 if (skip && (*skip)(newpath)) {
4378 continue;
4379 }
4380 if (d->d_type == DT_DIR) {
4381 int ret = dump_files("", newpath, skip, dump_from_fd);
4382 if (ret < 0) {
4383 retval = ret;
4384 }
4385 continue;
4386 }
4387 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
4388 if (fd.get() < 0) {
4389 retval = -1;
4390 printf("*** %s: %s\n", newpath, strerror(errno));
4391 continue;
4392 }
4393 (*dump_from_fd)(nullptr, newpath, fd.get());
4394 }
4395 closedir(dirp);
4396 if (!title.empty()) {
4397 printf("\n");
4398 }
4399 return retval;
4400}
4401
4402/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
4403 * it's possible to avoid issues where opening the file itself can get
4404 * stuck.
4405 */
4406int dump_file_from_fd(const char *title, const char *path, int fd) {
4407 if (PropertiesHelper::IsDryRun()) return 0;
4408
4409 int flags = fcntl(fd, F_GETFL);
4410 if (flags == -1) {
4411 printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
4412 return -1;
4413 } else if (!(flags & O_NONBLOCK)) {
4414 printf("*** %s: fd must have O_NONBLOCK set.\n", path);
4415 return -1;
4416 }
4417 return DumpFileFromFdToFd(title, path, fd, STDOUT_FILENO, PropertiesHelper::IsDryRun());
4418}
4419
4420int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004421 const CommandOptions& options, bool verbose_duration, int out_fd) {
4422 DurationReporter duration_reporter(title, false /* logcat_only */,
4423 verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004424
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004425 int status = RunCommandToFd(out_fd, title, full_command, options);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004426
4427 /* TODO: for now we're simplifying the progress calculation by using the
4428 * timeout as the weight. It's a good approximation for most cases, except when calling dumpsys,
4429 * where its weight should be much higher proportionally to its timeout.
4430 * Ideally, it should use a options.EstimatedDuration() instead...*/
4431 UpdateProgress(options.Timeout());
4432
4433 return status;
4434}
4435
4436void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
Rhed Jaoe017f982020-07-21 17:58:41 +08004437 const CommandOptions& options, long dumpsysTimeoutMs, int out_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004438 long timeout_ms = dumpsysTimeoutMs > 0 ? dumpsysTimeoutMs : options.TimeoutInMs();
4439 std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-T", std::to_string(timeout_ms)};
4440 dumpsys.insert(dumpsys.end(), dumpsys_args.begin(), dumpsys_args.end());
Rhed Jaoe017f982020-07-21 17:58:41 +08004441 RunCommand(title, dumpsys, options, false, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004442}
4443
Dieter Hsu105ad0c2020-09-29 15:23:33 +08004444static int open_socket(const char* service) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004445 int s = android_get_control_socket(service);
4446 if (s < 0) {
4447 MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
4448 return -1;
4449 }
4450 fcntl(s, F_SETFD, FD_CLOEXEC);
4451
4452 // Set backlog to 0 to make sure that queue size will be minimum.
4453 // In Linux, because the minimum queue will be 1, connect() will be blocked
4454 // if the other clients already called connect() and the connection request was not accepted.
4455 if (listen(s, 0) < 0) {
4456 MYLOGE("listen(control socket): %s\n", strerror(errno));
4457 return -1;
4458 }
4459
4460 struct sockaddr addr;
4461 socklen_t alen = sizeof(addr);
Abhijeet Kaur2113cae2019-09-13 09:24:15 +01004462 int fd = accept4(s, &addr, &alen, SOCK_CLOEXEC);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004463
4464 // Close socket just after accept(), to make sure that connect() by client will get error
4465 // when the socket is used by the other services.
4466 // There is still a race condition possibility between accept and close, but there is no way
4467 // to close-on-accept atomically.
4468 // See detail; b/123306389#comment25
4469 close(s);
4470
4471 if (fd < 0) {
4472 MYLOGE("accept(control socket): %s\n", strerror(errno));
4473 return -1;
4474 }
4475
4476 return fd;
4477}
4478
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004479// TODO: should call is_valid_output_file and/or be merged into it.
4480void create_parent_dirs(const char *path) {
4481 char *chp = const_cast<char *> (path);
4482
4483 /* skip initial slash */
4484 if (chp[0] == '/')
4485 chp++;
4486
4487 /* create leading directories, if necessary */
4488 struct stat dir_stat;
4489 while (chp && chp[0]) {
4490 chp = strchr(chp, '/');
4491 if (chp) {
4492 *chp = 0;
4493 if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
4494 MYLOGI("Creating directory %s\n", path);
4495 if (mkdir(path, 0770)) { /* drwxrwx--- */
4496 MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
4497 } else if (chown(path, AID_SHELL, AID_SHELL)) {
4498 MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
4499 }
4500 }
4501 *chp++ = '/';
4502 }
4503 }
4504}
4505
4506bool _redirect_to_file(FILE* redirect, char* path, int truncate_flag) {
4507 create_parent_dirs(path);
4508
4509 int fd = TEMP_FAILURE_RETRY(open(path,
4510 O_WRONLY | O_CREAT | truncate_flag | O_CLOEXEC | O_NOFOLLOW,
4511 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
4512 if (fd < 0) {
4513 MYLOGE("%s: %s\n", path, strerror(errno));
4514 return false;
4515 }
4516
4517 TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
4518 close(fd);
4519 return true;
4520}
4521
4522bool redirect_to_file(FILE* redirect, char* path) {
4523 return _redirect_to_file(redirect, path, O_TRUNC);
4524}
4525
4526bool redirect_to_existing_file(FILE* redirect, char* path) {
4527 return _redirect_to_file(redirect, path, O_APPEND);
4528}
4529
4530void dump_route_tables() {
4531 DurationReporter duration_reporter("DUMP ROUTE TABLES");
4532 if (PropertiesHelper::IsDryRun()) return;
4533 const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
4534 ds.DumpFile("RT_TABLES", RT_TABLES_PATH);
4535 FILE* fp = fopen(RT_TABLES_PATH, "re");
4536 if (!fp) {
4537 printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
4538 return;
4539 }
4540 char table[16];
4541 // Each line has an integer (the table number), a space, and a string (the table name). We only
4542 // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
4543 // Add a fixed max limit so this doesn't go awry.
4544 for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
4545 RunCommand("ROUTE TABLE IPv4", {"ip", "-4", "route", "show", "table", table});
4546 RunCommand("ROUTE TABLE IPv6", {"ip", "-6", "route", "show", "table", table});
4547 }
4548 fclose(fp);
4549}
4550
Li Li830179f2022-01-04 12:53:29 -08004551void dump_frozen_cgroupfs(const char *dir, int level,
4552 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4553 DIR *dirp;
4554 struct dirent *d;
4555 char *newpath = nullptr;
4556
4557 dirp = opendir(dir);
4558 if (dirp == nullptr) {
4559 MYLOGE("%s: %s\n", dir, strerror(errno));
4560 return;
4561 }
4562
4563 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4564 if ((d->d_name[0] == '.')
4565 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4566 || (d->d_name[1] == '\0'))) {
4567 continue;
4568 }
4569 if (d->d_type == DT_DIR) {
4570 asprintf(&newpath, "%s/%s/", dir, d->d_name);
4571 if (!newpath) {
4572 continue;
4573 }
4574 if (level == 0 && !strncmp(d->d_name, "uid_", 4)) {
4575 dump_frozen_cgroupfs(newpath, 1, dump_from_fd);
4576 } else if (level == 1 && !strncmp(d->d_name, "pid_", 4)) {
4577 char *freezer = nullptr;
4578 asprintf(&freezer, "%s/%s", newpath, "cgroup.freeze");
4579 if (freezer) {
4580 FILE* fp = fopen(freezer, "r");
4581 if (fp != NULL) {
4582 int frozen;
4583 fscanf(fp, "%d", &frozen);
4584 if (frozen > 0) {
4585 dump_files("", newpath, skip_none, dump_from_fd);
4586 }
4587 fclose(fp);
4588 }
4589 free(freezer);
4590 }
4591 }
4592 }
4593 }
4594 closedir(dirp);
4595}
4596
4597void dump_frozen_cgroupfs() {
Li Li830179f2022-01-04 12:53:29 -08004598 MYLOGD("Adding frozen processes from %s\n", CGROUPFS_DIR);
4599 DurationReporter duration_reporter("FROZEN CGROUPFS");
4600 if (PropertiesHelper::IsDryRun()) return;
4601 dump_frozen_cgroupfs(CGROUPFS_DIR, 0, _add_file_from_fd);
4602}
4603
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004604void Dumpstate::UpdateProgress(int32_t delta_sec) {
4605 if (progress_ == nullptr) {
4606 MYLOGE("UpdateProgress: progress_ not set\n");
4607 return;
4608 }
Rhed Jaobf63d8a2020-07-21 15:42:55 +08004609 // This function updates progress related members of the dumpstate and reports
4610 // progress percentage to the bugreport client. Since it could be called by
4611 // different dump tasks at the same time if the parallel run is enabled, a
4612 // mutex lock is necessary here to synchronize the call.
4613 std::lock_guard<std::recursive_mutex> lock(mutex_);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004614
4615 // Always update progess so stats can be tuned...
Nandana Dutt402a8392019-06-14 14:25:13 +01004616 progress_->Inc(delta_sec);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004617
4618 // ...but only notifiy listeners when necessary.
4619 if (!options_->do_progress_updates) return;
4620
4621 int progress = progress_->Get();
4622 int max = progress_->GetMax();
Nandana Dutt402a8392019-06-14 14:25:13 +01004623 int percent = 100 * progress / max;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004624
Nandana Dutt402a8392019-06-14 14:25:13 +01004625 if (last_reported_percent_progress_ > 0 && percent <= last_reported_percent_progress_) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004626 return;
4627 }
Nandana Dutt402a8392019-06-14 14:25:13 +01004628 last_reported_percent_progress_ = percent;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004629
4630 if (control_socket_fd_ >= 0) {
4631 dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
4632 fsync(control_socket_fd_);
4633 }
4634
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004635 if (listener_ != nullptr) {
Nandana Dutt235c6672019-11-14 15:22:32 +00004636 if (percent % 10 == 0) {
4637 // We don't want to spam logcat, so only log multiples of 10.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004638 MYLOGD("Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004639 } else {
4640 // stderr is ignored on normal invocations, but useful when calling
4641 // /system/bin/dumpstate directly for debuggging.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004642 fprintf(stderr, "Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004643 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004644
4645 listener_->onProgress(percent);
4646 }
4647}
4648
4649void Dumpstate::TakeScreenshot(const std::string& path) {
4650 const std::string& real_path = path.empty() ? screenshot_path_ : path;
4651 int status =
Abdelrahman Daim30e23602024-08-20 02:19:37 -07004652 RunCommand("", {"screencap", "-p", real_path},
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004653 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
4654 if (status == 0) {
4655 MYLOGD("Screenshot saved on %s\n", real_path.c_str());
4656 } else {
4657 MYLOGE("Failed to take screenshot on %s\n", real_path.c_str());
4658 }
Paul Chang0d2aad72020-02-13 20:04:03 +08004659 if (listener_ != nullptr) {
4660 // Show a visual indication to indicate screenshot is taken via
4661 // IDumpstateListener.onScreenshotTaken()
4662 listener_->onScreenshotTaken(status == 0);
4663 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004664}
4665
4666bool is_dir(const char* pathname) {
4667 struct stat info;
4668 if (stat(pathname, &info) == -1) {
4669 return false;
4670 }
4671 return S_ISDIR(info.st_mode);
4672}
4673
4674time_t get_mtime(int fd, time_t default_mtime) {
4675 struct stat info;
4676 if (fstat(fd, &info) == -1) {
4677 return default_mtime;
4678 }
4679 return info.st_mtime;
4680}