blob: d427ecf280a15ad3a4e23a400bd26edaaefc165a [file] [log] [blame]
Colin Crossf45fa6b2012-03-26 12:38:26 -07001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Felipe Lemef0292972016-11-22 13:57:05 -080016
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070017#define LOG_TAG "dumpstate"
Kevin Jeon2c02e8e2022-07-07 21:45:17 +000018#define ATRACE_TAG ATRACE_TAG_ALWAYS
Colin Crossf45fa6b2012-03-26 12:38:26 -070019
Pablo Gamito654831c2024-02-16 16:47:48 +000020#include "dumpstate.h"
Colin Crossf45fa6b2012-03-26 12:38:26 -070021
Kedar Chitnis9fd8c052021-11-16 09:09:22 +000022#include <aidl/android/hardware/dumpstate/IDumpstateDevice.h>
Felipe Leme96c2bbb2016-09-26 09:21:21 -070023#include <android-base/file.h>
24#include <android-base/properties.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070025#include <android-base/scopeguard.h>
Elliott Hughes9dc117c2015-12-07 14:21:50 -080026#include <android-base/stringprintf.h>
Naveen Kalla058e1e82016-10-19 21:38:44 -070027#include <android-base/strings.h>
Andreas Gampeaff68432016-07-18 18:01:27 -070028#include <android-base/unique_fd.h>
Kedar Chitnis9fd8c052021-11-16 09:09:22 +000029#include <android/binder_manager.h>
30#include <android/binder_process.h>
Nikita Ioffea325a572019-05-16 19:49:47 +010031#include <android/content/pm/IPackageManagerNative.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080032#include <android/hardware/dumpstate/1.0/IDumpstateDevice.h>
Hunter Knepshield8540faf2020-02-04 19:47:20 -080033#include <android/hardware/dumpstate/1.1/IDumpstateDevice.h>
34#include <android/hardware/dumpstate/1.1/types.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080035#include <android/hidl/manager/1.0/IServiceManager.h>
Nandana Duttd2f5f082019-01-18 17:13:52 +000036#include <android/os/IIncidentCompanion.h>
Pablo Gamito654831c2024-02-16 16:47:48 +000037#include <android_app_admin_flags.h>
38#include <android_tracing.h>
Nikita Ioffea325a572019-05-16 19:49:47 +010039#include <binder/IServiceManager.h>
Nikhil Kumar28ce35e2023-01-10 14:32:44 +000040#include <cutils/multiuser.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080041#include <cutils/native_handle.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070042#include <cutils/properties.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010043#include <cutils/sockets.h>
Kevin Jeon2c02e8e2022-07-07 21:45:17 +000044#include <cutils/trace.h>
Nandana Duttfaafd522019-03-11 09:23:09 +000045#include <debuggerd/client.h>
Pablo Gamito654831c2024-02-16 16:47:48 +000046#include <dirent.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080047#include <dumpsys.h>
Nandana Duttfaafd522019-03-11 09:23:09 +000048#include <dumputils/dump_utils.h>
Pablo Gamito654831c2024-02-16 16:47:48 +000049#include <errno.h>
50#include <fcntl.h>
Sahana Raof35ed432019-07-12 10:47:52 +010051#include <hardware_legacy/power.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080052#include <hidl/ServiceManagement.h>
Pablo Gamito654831c2024-02-16 16:47:48 +000053#include <inttypes.h>
54#include <libgen.h>
55#include <limits.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010056#include <log/log.h>
Tom Cherryf4472f32020-08-05 09:31:17 -070057#include <log/log_read.h>
Pablo Gamito654831c2024-02-16 16:47:48 +000058#include <math.h>
Felipe Leme75876a22016-10-27 16:31:27 -070059#include <openssl/sha.h>
Pablo Gamito654831c2024-02-16 16:47:48 +000060#include <poll.h>
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070061#include <private/android_filesystem_config.h>
62#include <private/android_logger.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080063#include <serviceutils/PriorityDumper.h>
Pablo Gamito654831c2024-02-16 16:47:48 +000064#include <signal.h>
65#include <stdarg.h>
66#include <stdbool.h>
67#include <stdio.h>
68#include <stdlib.h>
69#include <string.h>
70#include <sys/capability.h>
71#include <sys/inotify.h>
72#include <sys/klog.h>
73#include <sys/mount.h>
74#include <sys/poll.h>
75#include <sys/prctl.h>
76#include <sys/resource.h>
77#include <sys/stat.h>
78#include <sys/time.h>
79#include <sys/wait.h>
80#include <time.h>
81#include <unistd.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070082#include <utils/StrongPointer.h>
Devin Moore8df81bb2022-06-08 22:47:02 +000083#include <vintf/VintfObject.h>
Pablo Gamito654831c2024-02-16 16:47:48 +000084
85#include <chrono>
86#include <cmath>
87#include <fstream>
88#include <functional>
89#include <future>
90#include <memory>
91#include <numeric>
92#include <regex>
93#include <set>
94#include <string>
95#include <utility>
96#include <vector>
97
Felipe Lemef0292972016-11-22 13:57:05 -080098#include "DumpstateInternal.h"
Felipe Leme75876a22016-10-27 16:31:27 -070099#include "DumpstateService.h"
Felipe Leme6e01fa62015-11-11 19:35:14 -0800100
Kedar Chitnis9fd8c052021-11-16 09:09:22 +0000101namespace dumpstate_hal_hidl_1_0 = android::hardware::dumpstate::V1_0;
102namespace dumpstate_hal_hidl = android::hardware::dumpstate::V1_1;
103namespace dumpstate_hal_aidl = aidl::android::hardware::dumpstate;
104
Vishnu Naire97d6122018-01-18 13:58:56 -0800105using ::std::literals::chrono_literals::operator""ms;
106using ::std::literals::chrono_literals::operator""s;
Rhed Jao5377d792020-07-16 17:37:39 +0800107using ::std::placeholders::_1;
Steven Morelandcb7ef822016-11-29 13:20:37 -0800108
Felipe Leme47e9be22016-12-21 15:37:07 -0800109// TODO: remove once moved to namespace
Vishnu Naire97d6122018-01-18 13:58:56 -0800110using android::defaultServiceManager;
111using android::Dumpsys;
112using android::INVALID_OPERATION;
113using android::IServiceManager;
114using android::OK;
115using android::sp;
116using android::status_t;
117using android::String16;
118using android::String8;
119using android::TIMED_OUT;
120using android::UNKNOWN_ERROR;
121using android::Vector;
Nandana Dutt979388e2018-11-30 16:48:55 +0000122using android::base::StringPrintf;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000123using android::os::IDumpstateListener;
Felipe Leme47e9be22016-12-21 15:37:07 -0800124using android::os::dumpstate::CommandOptions;
125using android::os::dumpstate::DumpFileToFd;
Rhed Jao5377d792020-07-16 17:37:39 +0800126using android::os::dumpstate::DumpPool;
Vishnu Naire97d6122018-01-18 13:58:56 -0800127using android::os::dumpstate::PropertiesHelper;
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800128using android::os::dumpstate::TaskQueue;
Chris Morinbc223142022-02-04 14:17:11 -0800129using android::os::dumpstate::WaitForTask;
Felipe Leme47e9be22016-12-21 15:37:07 -0800130
Abhijeet Kaurcf234e82019-07-01 14:53:55 +0100131// Keep in sync with
132// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
133static const int TRACE_DUMP_TIMEOUT_MS = 10000; // 10 seconds
134
135/* Most simple commands have 10 as timeout, so 5 is a good estimate */
136static const int32_t WEIGHT_FILE = 5;
137
138// TODO: temporary variables and functions used during C++ refactoring
139static Dumpstate& ds = Dumpstate::GetInstance();
140static int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Nandana Dutt8d945c02019-08-14 13:30:07 +0100141 const CommandOptions& options = CommandOptions::DEFAULT,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800142 bool verbose_duration = false, int out_fd = STDOUT_FILENO) {
143 return ds.RunCommand(title, full_command, options, verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +0100144}
145
146// Reasonable value for max stats.
147static const int STATS_MAX_N_RUNS = 1000;
148static const long STATS_MAX_AVERAGE = 100000;
149
150CommandOptions Dumpstate::DEFAULT_DUMPSYS = CommandOptions::WithTimeout(30).Build();
151
Nandana Duttd2f5f082019-01-18 17:13:52 +0000152typedef Dumpstate::ConsentCallback::ConsentResult UserConsentResult;
153
Colin Crossf45fa6b2012-03-26 12:38:26 -0700154/* read before root is shed */
155static char cmdline_buf[16384] = "(unknown)";
Yi Kong19d5c002018-07-20 13:39:55 -0700156static const char *dump_traces_path = nullptr;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000157static const uint64_t USER_CONSENT_TIMEOUT_MS = 30 * 1000;
Hunter Knepshield70610fa2020-01-03 15:27:33 -0800158// Because telephony reports are significantly faster to collect (< 10 seconds vs. > 2 minutes),
159// it's often the case that they time out far too quickly for consent with such a hefty dialog for
160// the user to read. For telephony reports only, we increase the default timeout to 2 minutes to
161// roughly match full reports' durations.
162static const uint64_t TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS = 2 * 60 * 1000;
Colin Crossf45fa6b2012-03-26 12:38:26 -0700163
Felipe Leme1d486fe2016-10-14 18:06:47 -0700164// TODO: variables and functions below should be part of dumpstate object
165
Felipe Leme635ca312016-01-05 14:23:02 -0800166static std::set<std::string> mount_points;
167void add_mountinfo();
Felipe Leme78f2c862015-12-21 09:55:22 -0800168
Todd Poynor2a83daa2013-11-22 15:44:22 -0800169#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
Mark Salyzyn7d0a7622016-06-24 14:06:15 -0700170#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
Wei Wang509bb5d2017-06-09 14:42:12 -0700171#define BLK_DEV_SYS_DIR "/sys/block"
Todd Poynor2a83daa2013-11-22 15:44:22 -0800172
Ted Bauerf6d61b82024-09-13 19:57:19 +0000173#define AFLAGS "/system/bin/aflags"
Felipe Lemee82a27d2016-01-05 13:35:44 -0800174#define RECOVERY_DIR "/cache/recovery"
Mark Salyzynd6ab0112016-03-25 12:56:39 -0700175#define RECOVERY_DATA_DIR "/data/misc/recovery"
Tianjie Xu75d53362018-04-11 16:42:28 -0700176#define UPDATE_ENGINE_LOG_DIR "/data/misc/update_engine_log"
Kelvin Zhang6eaa0f92022-09-12 09:29:19 -0700177#define UPDATE_ENGINE_PREF_DIR "/data/misc/update_engine/prefs"
Mark Salyzyn4d42dea2016-04-01 10:03:14 -0700178#define LOGPERSIST_DATA_DIR "/data/misc/logd"
Jerry Changa1df8a92020-01-02 16:03:39 +0800179#define PREREBOOT_DATA_DIR "/data/misc/prereboot"
David Brazdild2991962016-06-03 14:40:44 +0100180#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
181#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
Benedict Wong8f9d8a42019-01-03 16:19:38 -0800182#define XFRM_STAT_PROC_FILE "/proc/net/xfrm_stat"
Steven Moreland9379c462023-12-21 02:04:27 +0000183#define KERNEL_CONFIG "/proc/config.gz"
Erik Kline08165202016-05-30 11:55:44 +0900184#define WLUTIL "/vendor/xbin/wlutil"
Vishnu Nair36b4cdb2017-11-17 10:27:05 -0800185#define WMTRACE_DATA_DIR "/data/misc/wmtrace"
Yifan Hong3945e1b2019-10-29 12:59:23 -0700186#define OTA_METADATA_DIR "/metadata/ota"
Yifan Hong0efa7972020-02-03 16:45:02 -0800187#define SNAPSHOTCTL_LOG_DIR "/data/misc/snapshotctl_log"
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +0900188#define LINKERCONFIG_DIR "/linkerconfig"
Calin Juravlef84d3692020-04-28 15:31:12 -0700189#define PACKAGE_DEX_USE_LIST "/data/system/package-dex-usage.list"
Primiano Tuccifaaaafb2021-01-14 12:26:29 +0000190#define SYSTEM_TRACE_SNAPSHOT "/data/misc/perfetto-traces/bugreport/systrace.pftrace"
Li Li2eedd412021-06-30 15:11:53 -0700191#define CGROUPFS_DIR "/sys/fs/cgroup"
MÃ¥rten Kongstad60195a72022-09-20 14:14:20 +0200192#define SDK_EXT_INFO "/apex/com.android.sdkext/bin/derive_sdk"
Jeff Sharkey9df29d52023-02-06 14:26:30 -0700193#define DROPBOX_DIR "/data/system/dropbox"
MÃ¥rten Kongstad5ad813f2023-09-28 10:09:18 +0200194#define PRINT_FLAGS "/system/bin/printflags"
Nattharat Jariyanuntanaetb250cae2024-05-15 07:48:19 +0000195#define UWB_LOG_DIR "/data/misc/apexdata/com.android.uwb/log"
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700196
Narayan Kamath8f788292017-05-25 13:20:39 +0100197// TODO(narayan): Since this information has to be kept in sync
198// with tombstoned, we should just put it in a common header.
199//
200// File: system/core/debuggerd/tombstoned/tombstoned.cpp
Narayan Kamathbd863722017-06-01 18:50:12 +0100201static const std::string TOMBSTONE_DIR = "/data/tombstones/";
202static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
203static const std::string ANR_DIR = "/data/anr/";
204static const std::string ANR_FILE_PREFIX = "anr_";
Andy Hungd62f7e62024-01-11 15:47:52 -0800205static const std::string ANR_TRACE_FILE_PREFIX = "trace_";
Woody Lin20767a92022-11-29 15:50:24 +0800206static const std::string SHUTDOWN_CHECKPOINTS_DIR = "/data/system/shutdown-checkpoints/";
207static const std::string SHUTDOWN_CHECKPOINTS_FILE_PREFIX = "checkpoints-";
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700208
Felipe Lemee844a9d2016-09-21 15:01:39 -0700209// TODO: temporary variables and functions used during C++ refactoring
Nandana Dutt979388e2018-11-30 16:48:55 +0000210
Nandana Dutt5c390032019-03-12 10:52:56 +0000211#define RETURN_IF_USER_DENIED_CONSENT() \
212 if (ds.IsUserConsentDenied()) { \
213 MYLOGE("Returning early as user denied consent to share bugreport with calling app."); \
214 return Dumpstate::RunStatus::USER_CONSENT_DENIED; \
215 }
216
217// Runs func_ptr, but checks user consent before and after running it. Returns USER_CONSENT_DENIED
218// if consent is found to be denied.
219#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(func_ptr, ...) \
220 RETURN_IF_USER_DENIED_CONSENT(); \
221 func_ptr(__VA_ARGS__); \
222 RETURN_IF_USER_DENIED_CONSENT();
223
Rhed Jao5377d792020-07-16 17:37:39 +0800224// Runs func_ptr, and logs a duration report after it's finished.
225#define RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, ...) \
226 { \
227 DurationReporter duration_reporter_in_macro(log_title); \
228 func_ptr(__VA_ARGS__); \
229 }
230
231// Similar with RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK, an additional duration report
232// is output after a slow function is finished.
233#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(log_title, func_ptr, ...) \
234 RETURN_IF_USER_DENIED_CONSENT(); \
235 RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, __VA_ARGS__); \
236 RETURN_IF_USER_DENIED_CONSENT();
237
Chris Morinbc223142022-02-04 14:17:11 -0800238#define WAIT_TASK_WITH_CONSENT_CHECK(future) \
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800239 RETURN_IF_USER_DENIED_CONSENT(); \
Chris Morinbc223142022-02-04 14:17:11 -0800240 WaitForTask(future); \
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800241 RETURN_IF_USER_DENIED_CONSENT();
242
Sahana Raof35ed432019-07-12 10:47:52 +0100243static const char* WAKE_LOCK_NAME = "dumpstate_wakelock";
244
Rhed Jao5377d792020-07-16 17:37:39 +0800245// Names of parallel tasks, they are used for the DumpPool to identify the dump
246// task and the log title of the duration report.
247static const std::string DUMP_TRACES_TASK = "DUMP TRACES";
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800248static const std::string DUMP_INCIDENT_REPORT_TASK = "INCIDENT REPORT";
Aaron Huang24d215d2022-04-27 18:51:16 +0800249static const std::string DUMP_NETSTATS_PROTO_TASK = "DUMP NETSTATS PROTO";
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800250static const std::string DUMP_HALS_TASK = "DUMP HALS";
251static const std::string DUMP_BOARD_TASK = "dumpstate_board()";
Rhed Jaoe017f982020-07-21 17:58:41 +0800252static const std::string DUMP_CHECKINS_TASK = "DUMP CHECKINS";
Kean Mariottica20f2d2023-12-15 09:34:25 +0000253static const std::string SERIALIZE_PERFETTO_TRACE_TASK = "SERIALIZE PERFETTO TRACE";
Rhed Jao5377d792020-07-16 17:37:39 +0800254
Nandana Dutt979388e2018-11-30 16:48:55 +0000255namespace android {
256namespace os {
257namespace {
258
259static int Open(std::string path, int flags, mode_t mode = 0) {
260 int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
261 if (fd == -1) {
262 MYLOGE("open(%s, %s)\n", path.c_str(), strerror(errno));
263 }
264 return fd;
265}
266
mhasank2d75c442020-06-11 15:05:25 -0700267static int OpenForWrite(std::string path) {
268 return Open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
269 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
270}
Nandana Dutt979388e2018-11-30 16:48:55 +0000271
272static int OpenForRead(std::string path) {
273 return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
274}
275
276bool CopyFile(int in_fd, int out_fd) {
277 char buf[4096];
278 ssize_t byte_count;
279 while ((byte_count = TEMP_FAILURE_RETRY(read(in_fd, buf, sizeof(buf)))) > 0) {
280 if (!android::base::WriteFully(out_fd, buf, byte_count)) {
281 return false;
282 }
283 }
284 return (byte_count != -1);
285}
286
287static bool CopyFileToFd(const std::string& input_file, int out_fd) {
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000288 MYLOGD("Going to copy file (%s) to %d\n", input_file.c_str(), out_fd);
Nandana Dutt979388e2018-11-30 16:48:55 +0000289
290 // Obtain a handle to the source file.
291 android::base::unique_fd in_fd(OpenForRead(input_file));
292 if (out_fd != -1 && in_fd.get() != -1) {
293 if (CopyFile(in_fd.get(), out_fd)) {
294 return true;
295 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000296 MYLOGE("Failed to copy file: %s\n", strerror(errno));
Nandana Dutt979388e2018-11-30 16:48:55 +0000297 }
298 return false;
299}
300
Nandana Duttd2f5f082019-01-18 17:13:52 +0000301static bool UnlinkAndLogOnError(const std::string& file) {
Nandana Dutt8ae16e62020-03-27 10:20:22 +0000302 if (file.empty()) {
303 return false;
304 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000305 if (unlink(file.c_str())) {
306 MYLOGE("Failed to unlink file (%s): %s\n", file.c_str(), strerror(errno));
Nandana Duttd2f5f082019-01-18 17:13:52 +0000307 return false;
308 }
309 return true;
310}
Nandana Dutt979388e2018-11-30 16:48:55 +0000311
Nikita Ioffea325a572019-05-16 19:49:47 +0100312int64_t GetModuleMetadataVersion() {
313 auto binder = defaultServiceManager()->getService(android::String16("package_native"));
314 if (binder == nullptr) {
315 MYLOGE("Failed to retrieve package_native service");
316 return 0L;
317 }
318 auto package_service = android::interface_cast<content::pm::IPackageManagerNative>(binder);
319 std::string package_name;
320 auto status = package_service->getModuleMetadataPackageName(&package_name);
321 if (!status.isOk()) {
322 MYLOGE("Failed to retrieve module metadata package name: %s", status.toString8().c_str());
323 return 0L;
324 }
Nandana Duttdb379fa2019-10-09 16:54:41 +0100325 MYLOGD("Module metadata package name: %s\n", package_name.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100326 int64_t version_code;
327 status = package_service->getVersionCodeForPackage(android::String16(package_name.c_str()),
328 &version_code);
329 if (!status.isOk()) {
330 MYLOGE("Failed to retrieve module metadata version: %s", status.toString8().c_str());
331 return 0L;
332 }
333 return version_code;
334}
335
mhasank2d75c442020-06-11 15:05:25 -0700336static bool PathExists(const std::string& path) {
337 struct stat sb;
338 return stat(path.c_str(), &sb) == 0;
339}
340
341static bool CopyFileToFile(const std::string& input_file, const std::string& output_file) {
342 if (input_file == output_file) {
343 MYLOGD("Skipping copying bugreport file since the destination is the same (%s)\n",
344 output_file.c_str());
345 return false;
346 }
347 else if (PathExists(output_file)) {
348 MYLOGD("Cannot overwrite an existing file (%s)\n", output_file.c_str());
349 return false;
350 }
351
352 MYLOGD("Going to copy bugreport file (%s) to %s\n", input_file.c_str(), output_file.c_str());
353 android::base::unique_fd out_fd(OpenForWrite(output_file));
354 return CopyFileToFd(input_file, out_fd.get());
355}
356
Nandana Dutt979388e2018-11-30 16:48:55 +0000357} // namespace
358} // namespace os
359} // namespace android
360
Felipe Leme678727a2016-09-21 17:22:11 -0700361static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
Felipe Lemebda15a02016-11-16 17:48:25 -0800362 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
Rhed Jaoe017f982020-07-21 17:58:41 +0800363 long dumpsysTimeoutMs = 0, int out_fd = STDOUT_FILENO) {
364 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs, out_fd);
365}
366static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
367 int out_fd) {
368 return ds.RunDumpsys(title, dumpsysArgs, Dumpstate::DEFAULT_DUMPSYS, 0, out_fd);
Felipe Leme678727a2016-09-21 17:22:11 -0700369}
370static int DumpFile(const std::string& title, const std::string& path) {
371 return ds.DumpFile(title, path);
372}
Felipe Lemee82a27d2016-01-05 13:35:44 -0800373
Felipe Lemee844a9d2016-09-21 15:01:39 -0700374// Relative directory (inside the zip) for all files copied as-is into the bugreport.
375static const std::string ZIP_ROOT_DIR = "FS";
376
Vishnu Naire97d6122018-01-18 13:58:56 -0800377static const std::string kProtoPath = "proto/";
378static const std::string kProtoExt = ".proto";
Jie Song9fbfad02017-06-20 16:29:42 -0700379static const std::string kDumpstateBoardFiles[] = {
380 "dumpstate_board.txt",
Felipe Leme95d6ca52017-08-01 16:35:56 -0700381 "dumpstate_board.bin"
Jie Song9fbfad02017-06-20 16:29:42 -0700382};
383static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
384
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700385static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Lemed071c682016-10-20 16:48:00 -0700386static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700387
Felipe Lemef0292972016-11-22 13:57:05 -0800388static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
389
Narayan Kamath8f788292017-05-25 13:20:39 +0100390/*
Narayan Kamathbd863722017-06-01 18:50:12 +0100391 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
Rhed Jao01dc0c62020-06-03 17:13:30 +0800392 * The returned vector is sorted by the mtimes of the dumps with descending
Chris Morinc2cba7a2022-02-01 17:06:50 -0800393 * order.
Narayan Kamath8f788292017-05-25 13:20:39 +0100394 */
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700395static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
Chris Morinc2cba7a2022-02-01 17:06:50 -0800396 const std::string& file_prefix) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100397 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100398
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700399 if (dump_dir == nullptr) {
400 MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno));
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700401 return std::vector<DumpData>();
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700402 }
403
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700404 std::vector<DumpData> dump_data;
Narayan Kamathbd863722017-06-01 18:50:12 +0100405 struct dirent* entry = nullptr;
406 while ((entry = readdir(dump_dir.get()))) {
407 if (entry->d_type != DT_REG) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100408 continue;
409 }
410
Narayan Kamathbd863722017-06-01 18:50:12 +0100411 const std::string base_name(entry->d_name);
412 if (base_name.find(file_prefix) != 0) {
413 continue;
414 }
415
416 const std::string abs_path = dir_path + base_name;
417 android::base::unique_fd fd(
418 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
419 if (fd == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700420 MYLOGW("Unable to open dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamathbd863722017-06-01 18:50:12 +0100421 break;
422 }
423
424 struct stat st = {};
425 if (fstat(fd, &st) == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700426 MYLOGW("Unable to stat dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamath8f788292017-05-25 13:20:39 +0100427 continue;
428 }
429
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700430 dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700431 }
Rhed Jao01dc0c62020-06-03 17:13:30 +0800432 if (!dump_data.empty()) {
433 std::sort(dump_data.begin(), dump_data.end(),
434 [](const auto& a, const auto& b) { return a.mtime > b.mtime; });
435 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100436
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700437 return dump_data;
Narayan Kamath8f788292017-05-25 13:20:39 +0100438}
439
Narayan Kamathbd863722017-06-01 18:50:12 +0100440static bool AddDumps(const std::vector<DumpData>::const_iterator start,
441 const std::vector<DumpData>::const_iterator end,
442 const char* type_name, const bool add_to_zip) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100443 bool dumped = false;
Narayan Kamathbd863722017-06-01 18:50:12 +0100444 for (auto it = start; it != end; ++it) {
445 const std::string& name = it->name;
446 const int fd = it->fd;
Narayan Kamath8f788292017-05-25 13:20:39 +0100447 dumped = true;
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100448
449 // Seek to the beginning of the file before dumping any data. A given
450 // DumpData entry might be dumped multiple times in the report.
451 //
452 // For example, the most recent ANR entry is dumped to the body of the
453 // main entry and it also shows up as a separate entry in the bugreport
454 // ZIP file.
455 if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) {
456 MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(),
457 strerror(errno));
458 }
459
Chris Morinc2cba7a2022-02-01 17:06:50 -0800460 if (add_to_zip) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800461 if (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd, /* timeout = */ 0ms) != OK) {
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100462 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100463 }
464 } else {
465 dump_file_from_fd(type_name, name.c_str(), fd);
466 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100467 }
468
469 return dumped;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700470}
471
Felipe Leme635ca312016-01-05 14:23:02 -0800472// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700473void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800474 char path[PATH_MAX];
475
476 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
477 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700478 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800479 char linkname[PATH_MAX];
480 ssize_t r = readlink(path, linkname, PATH_MAX);
481 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800482 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800483 return;
484 }
485 linkname[r] = '\0';
486
487 if (mount_points.find(linkname) == mount_points.end()) {
488 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700489 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700490 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
Felipe Leme635ca312016-01-05 14:23:02 -0800491 mount_points.insert(linkname);
492 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800493 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800494 }
495 }
496}
497
498void add_mountinfo() {
Felipe Leme678727a2016-09-21 17:22:11 -0700499 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800500 mount_points.clear();
Felipe Leme46b85da2016-11-21 17:40:45 -0800501 DurationReporter duration_reporter(title, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700502 for_each_pid(do_mountinfo, nullptr);
503 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800504}
505
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700506static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
507{
508 DIR *d;
509 struct dirent *de;
510 char path[PATH_MAX];
511
512 d = opendir(driverpath);
Yi Kong19d5c002018-07-20 13:39:55 -0700513 if (d == nullptr) {
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700514 return;
515 }
516
517 while ((de = readdir(d))) {
518 if (de->d_type != DT_LNK) {
519 continue;
520 }
521 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700522 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700523 }
524
525 closedir(d);
526}
527
Mark Salyzyn326842f2015-04-30 09:49:41 -0700528static bool skip_not_stat(const char *path) {
529 static const char stat[] = "/stat";
530 size_t len = strlen(path);
531 if (path[len - 1] == '/') { /* Directory? */
532 return false;
533 }
534 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
535}
536
Jeff Sharkey9df29d52023-02-06 14:26:30 -0700537static bool skip_wtf_strictmode(const char *path) {
538 if (strstr(path, "_wtf")) {
539 return true;
540 } else if (strstr(path, "_strictmode")) {
541 return true;
542 }
543 return false;
544}
545
Felipe Leme4c2d6632016-09-28 14:32:00 -0700546static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800547 return false;
548}
549
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700550unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700551
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800552//
553// stat offsets
554// Name units description
555// ---- ----- -----------
556// read I/Os requests number of read I/Os processed
557#define __STAT_READ_IOS 0
558// read merges requests number of read I/Os merged with in-queue I/O
559#define __STAT_READ_MERGES 1
560// read sectors sectors number of sectors read
561#define __STAT_READ_SECTORS 2
562// read ticks milliseconds total wait time for read requests
563#define __STAT_READ_TICKS 3
564// write I/Os requests number of write I/Os processed
565#define __STAT_WRITE_IOS 4
566// write merges requests number of write I/Os merged with in-queue I/O
567#define __STAT_WRITE_MERGES 5
568// write sectors sectors number of sectors written
569#define __STAT_WRITE_SECTORS 6
570// write ticks milliseconds total wait time for write requests
571#define __STAT_WRITE_TICKS 7
572// in_flight requests number of I/Os currently in flight
573#define __STAT_IN_FLIGHT 8
574// io_ticks milliseconds total time this block device has been active
575#define __STAT_IO_TICKS 9
576// time_in_queue milliseconds total wait time for all requests
577#define __STAT_IN_QUEUE 10
578#define __STAT_NUMBER_FIELD 11
579//
580// read I/Os, write I/Os
581// =====================
582//
583// These values increment when an I/O request completes.
584//
585// read merges, write merges
586// =========================
587//
588// These values increment when an I/O request is merged with an
589// already-queued I/O request.
590//
591// read sectors, write sectors
592// ===========================
593//
594// These values count the number of sectors read from or written to this
595// block device. The "sectors" in question are the standard UNIX 512-byte
596// sectors, not any device- or filesystem-specific block size. The
597// counters are incremented when the I/O completes.
598#define SECTOR_SIZE 512
599//
600// read ticks, write ticks
601// =======================
602//
603// These values count the number of milliseconds that I/O requests have
604// waited on this block device. If there are multiple I/O requests waiting,
605// these values will increase at a rate greater than 1000/second; for
606// example, if 60 read requests wait for an average of 30 ms, the read_ticks
607// field will increase by 60*30 = 1800.
608//
609// in_flight
610// =========
611//
612// This value counts the number of I/O requests that have been issued to
613// the device driver but have not yet completed. It does not include I/O
614// requests that are in the queue but not yet issued to the device driver.
615//
616// io_ticks
617// ========
618//
619// This value counts the number of milliseconds during which the device has
620// had I/O requests queued.
621//
622// time_in_queue
623// =============
624//
625// This value counts the number of milliseconds that I/O requests have waited
626// on this block device. If there are multiple I/O requests waiting, this
627// value will increase as the product of the number of milliseconds times the
628// number of requests waiting (see "read ticks" above for an example).
629#define S_TO_MS 1000
630//
631
Mark Salyzyn326842f2015-04-30 09:49:41 -0700632static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800633 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700634 bool z;
Yi Kong19d5c002018-07-20 13:39:55 -0700635 char *cp, *buffer = nullptr;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700636 size_t i = 0;
Josh Gao7c4258c2018-06-25 13:40:08 -0700637 FILE *fp = fdopen(dup(fd), "rb");
Mark Salyzyn326842f2015-04-30 09:49:41 -0700638 getline(&buffer, &i, fp);
639 fclose(fp);
640 if (!buffer) {
641 return -errno;
642 }
643 i = strlen(buffer);
644 while ((i > 0) && (buffer[i - 1] == '\n')) {
645 buffer[--i] = '\0';
646 }
647 if (!*buffer) {
648 free(buffer);
649 return 0;
650 }
651 z = true;
652 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800653 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700654 if (fields[i] != 0) {
655 z = false;
656 }
657 }
658 if (z) { /* never accessed */
659 free(buffer);
660 return 0;
661 }
662
Wei Wang509bb5d2017-06-09 14:42:12 -0700663 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
664 path += sizeof(BLK_DEV_SYS_DIR) - 1;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700665 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700666
667 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
668 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
669 "W-wait", "in-fli", "activ", "T-wait", path, buffer);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700670 free(buffer);
671
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800672 if (fields[__STAT_IO_TICKS]) {
673 unsigned long read_perf = 0;
674 unsigned long read_ios = 0;
675 if (fields[__STAT_READ_TICKS]) {
676 unsigned long long divisor = fields[__STAT_READ_TICKS]
677 * fields[__STAT_IO_TICKS];
678 read_perf = ((unsigned long long)SECTOR_SIZE
679 * fields[__STAT_READ_SECTORS]
680 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
681 / divisor;
682 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
683 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
684 / divisor;
685 }
686
687 unsigned long write_perf = 0;
688 unsigned long write_ios = 0;
689 if (fields[__STAT_WRITE_TICKS]) {
690 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
691 * fields[__STAT_IO_TICKS];
692 write_perf = ((unsigned long long)SECTOR_SIZE
693 * fields[__STAT_WRITE_SECTORS]
694 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
695 / divisor;
696 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
697 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
698 / divisor;
699 }
700
701 unsigned queue = (fields[__STAT_IN_QUEUE]
702 + (fields[__STAT_IO_TICKS] >> 1))
703 / fields[__STAT_IO_TICKS];
704
705 if (!write_perf && !write_ios) {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700706 printf("%-30s: perf(ios) rd: %luKB/s(%lu/s) q: %u\n", path, read_perf, read_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800707 } else {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700708 printf("%-30s: perf(ios) rd: %luKB/s(%lu/s) wr: %luKB/s(%lu/s) q: %u\n", path, read_perf,
Felipe Lemed8b94e52016-12-08 10:21:44 -0800709 read_ios, write_perf, write_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800710 }
711
712 /* bugreport timeout factor adjustment */
713 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
714 worst_write_perf = write_perf;
715 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700716 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700717 return 0;
718}
719
Yao Chenbe3bbc12018-01-17 16:31:10 -0800720static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
721
Tom Cherryf4472f32020-08-05 09:31:17 -0700722// Returns the actual readable size of the given buffer or -1 on error.
723static long logcat_buffer_readable_size(const std::string& buffer) {
724 std::unique_ptr<logger_list, decltype(&android_logger_list_free)> logger_list{
725 android_logger_list_alloc(0, 0, 0), &android_logger_list_free};
726 auto logger = android_logger_open(logger_list.get(), android_name_to_log_id(buffer.c_str()));
727
728 return android_logger_get_log_readable_size(logger);
729}
730
731// Returns timeout in ms to read a list of buffers.
Yao Chenbe3bbc12018-01-17 16:31:10 -0800732static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
733 unsigned long timeout_ms = 0;
734 for (const auto& buffer : buffers) {
Tom Cherryf4472f32020-08-05 09:31:17 -0700735 long readable_size = logcat_buffer_readable_size(buffer);
736 if (readable_size > 0) {
737 // Engineering margin is ten-fold our guess.
738 timeout_ms += 10 * (readable_size + worst_write_perf) / worst_write_perf;
739 }
Yao Chenbe3bbc12018-01-17 16:31:10 -0800740 }
741 return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700742}
743
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800744// Opens a socket and returns its file descriptor.
745static int open_socket(const char* service);
746
Nandana Duttd2f5f082019-01-18 17:13:52 +0000747Dumpstate::ConsentCallback::ConsentCallback() : result_(UNAVAILABLE), start_time_(Nanotime()) {
748}
749
750android::binder::Status Dumpstate::ConsentCallback::onReportApproved() {
751 std::lock_guard<std::mutex> lock(lock_);
752 result_ = APPROVED;
753 MYLOGD("User approved consent to share bugreport\n");
Paul Chang0d2aad72020-02-13 20:04:03 +0800754
755 // Maybe copy screenshot so calling app can display the screenshot to the user as soon as
756 // consent is granted.
757 if (ds.options_->is_screenshot_copied) {
758 return android::binder::Status::ok();
759 }
760
761 if (!ds.options_->do_screenshot || ds.options_->screenshot_fd.get() == -1 ||
762 !ds.do_early_screenshot_) {
763 return android::binder::Status::ok();
764 }
765
766 bool copy_succeeded = android::os::CopyFileToFd(ds.screenshot_path_,
767 ds.options_->screenshot_fd.get());
768 ds.options_->is_screenshot_copied = copy_succeeded;
769 if (copy_succeeded) {
770 android::os::UnlinkAndLogOnError(ds.screenshot_path_);
771 }
Nandana Duttd2f5f082019-01-18 17:13:52 +0000772 return android::binder::Status::ok();
773}
774
775android::binder::Status Dumpstate::ConsentCallback::onReportDenied() {
776 std::lock_guard<std::mutex> lock(lock_);
777 result_ = DENIED;
778 MYLOGW("User denied consent to share bugreport\n");
779 return android::binder::Status::ok();
780}
781
782UserConsentResult Dumpstate::ConsentCallback::getResult() {
783 std::lock_guard<std::mutex> lock(lock_);
784 return result_;
785}
786
787uint64_t Dumpstate::ConsentCallback::getElapsedTimeMs() const {
Hunter Knepshieldf0a39052020-01-03 14:53:04 -0800788 return (Nanotime() - start_time_) / NANOS_PER_MILLI;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000789}
790
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700791void Dumpstate::PrintHeader() const {
MÃ¥rten Kongstad60195a72022-09-20 14:14:20 +0200792 std::string build, fingerprint, radio, bootloader, network, sdkversion;
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700793 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700794
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700795 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
796 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700797 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
798 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
799 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
MÃ¥rten Kongstad60195a72022-09-20 14:14:20 +0200800 sdkversion = android::base::GetProperty("ro.build.version.sdk", "(unknown)");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700801 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
Colin Crossf45fa6b2012-03-26 12:38:26 -0700802
Felipe Lemed8b94e52016-12-08 10:21:44 -0800803 printf("========================================================\n");
804 printf("== dumpstate: %s\n", date);
805 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700806
Felipe Lemed8b94e52016-12-08 10:21:44 -0800807 printf("\n");
808 printf("Build: %s\n", build.c_str());
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700809 // NOTE: fingerprint entry format is important for other tools.
Felipe Lemed8b94e52016-12-08 10:21:44 -0800810 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
811 printf("Bootloader: %s\n", bootloader.c_str());
812 printf("Radio: %s\n", radio.c_str());
813 printf("Network: %s\n", network.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100814 int64_t module_metadata_version = android::os::GetModuleMetadataVersion();
815 if (module_metadata_version != 0) {
816 printf("Module Metadata version: %" PRId64 "\n", module_metadata_version);
817 }
MÃ¥rten Kongstad60195a72022-09-20 14:14:20 +0200818 printf("Android SDK version: %s\n", sdkversion.c_str());
819 printf("SDK extensions: ");
820 RunCommandToFd(STDOUT_FILENO, "", {SDK_EXT_INFO, "--header"},
821 CommandOptions::WithTimeout(1).Always().DropRoot().Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700822
Felipe Lemed8b94e52016-12-08 10:21:44 -0800823 printf("Kernel: ");
Felipe Lemef0292972016-11-22 13:57:05 -0800824 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
Felipe Lemed8b94e52016-12-08 10:21:44 -0800825 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
Devin Moore09fde8d2023-03-21 16:28:22 +0000826 printf("Bootconfig: ");
827 DumpFileToFd(STDOUT_FILENO, "", "/proc/bootconfig");
Felipe Leme7709f8a2017-12-05 09:30:09 -0800828 printf("Uptime: ");
829 RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"},
830 CommandOptions::WithTimeout(1).Always().Build());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800831 printf("Bugreport format version: %s\n", version_.c_str());
Kevin Jeonfa64e642023-07-27 11:36:41 -0400832 printf(
833 "Dumpstate info: id=%d pid=%d dry_run=%d parallel_run=%d strict_run=%d args=%s "
834 "bugreport_mode=%s\n",
835 id_, pid_, PropertiesHelper::IsDryRun(), PropertiesHelper::IsParallelRun(),
836 PropertiesHelper::IsStrictRun(), options_->args.c_str(),
837 options_->bugreport_mode_string.c_str());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800838 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800839}
840
Felipe Leme24b66ee2016-06-16 10:55:26 -0700841// List of file extensions that can cause a zip file attachment to be rejected by some email
842// service providers.
843static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
844 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
845 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
846 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
847};
848
Vishnu Naire97d6122018-01-18 13:58:56 -0800849status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd,
850 std::chrono::milliseconds timeout = 0ms) {
Felipe Leme24b66ee2016-06-16 10:55:26 -0700851 std::string valid_name = entry_name;
852
853 // Rename extension if necessary.
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -0700854 size_t idx = entry_name.rfind('.');
Felipe Leme24b66ee2016-06-16 10:55:26 -0700855 if (idx != std::string::npos) {
856 std::string extension = entry_name.substr(idx);
857 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
858 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
859 valid_name = entry_name + ".renamed";
860 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
861 }
862 }
863
Felipe Leme6fe9db62016-02-12 09:04:16 -0800864 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
865 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Kevin Jeon9bbe0ac2022-05-05 22:05:43 +0000866 size_t flags = ZipWriter::kCompress | ZipWriter::kDefaultCompression;
867 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), flags,
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700868 get_mtime(fd, ds.now_));
Felipe Leme1d486fe2016-10-14 18:06:47 -0700869 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700870 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700871 ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800872 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800873 }
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000874 bool finished_entry = false;
875 auto finish_entry = [this, &finished_entry] {
876 if (!finished_entry) {
877 // This should only be called when we're going to return an earlier error,
878 // which would've been logged. This may imply the file is already corrupt
879 // and any further logging from FinishEntry is more likely to mislead than
880 // not.
881 this->zip_writer_->FinishEntry();
882 }
883 };
884 auto scope_guard = android::base::make_scope_guard(finish_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -0800885 auto start = std::chrono::steady_clock::now();
886 auto end = start + timeout;
887 struct pollfd pfd = {fd, POLLIN};
Felipe Lemee82a27d2016-01-05 13:35:44 -0800888
Felipe Leme770410d2016-01-26 17:07:14 -0800889 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800890 while (1) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800891 if (timeout.count() > 0) {
892 // lambda to recalculate the timeout.
893 auto time_left_ms = [end]() {
894 auto now = std::chrono::steady_clock::now();
895 auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
896 return std::max(diff.count(), 0LL);
897 };
898
899 int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
900 if (rc < 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000901 MYLOGE("Error in poll while adding from fd to zip entry %s:%s\n",
902 entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800903 return -errno;
904 } else if (rc == 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000905 MYLOGE("Timed out adding from fd to zip entry %s:%s Timeout:%lldms\n",
Vishnu Naire97d6122018-01-18 13:58:56 -0800906 entry_name.c_str(), strerror(errno), timeout.count());
907 return TIMED_OUT;
908 }
909 }
910
Zach Riggle22200402016-08-18 01:01:24 -0400911 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800912 if (bytes_read == 0) {
913 break;
914 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800915 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800916 return -errno;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800917 }
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700918 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800919 if (err) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700920 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800921 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800922 }
923 }
924
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700925 err = zip_writer_->FinishEntry();
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000926 finished_entry = true;
Felipe Leme1d486fe2016-10-14 18:06:47 -0700927 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700928 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800929 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800930 }
931
Vishnu Naire97d6122018-01-18 13:58:56 -0800932 return OK;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800933}
934
Felipe Leme1d486fe2016-10-14 18:06:47 -0700935bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
936 android::base::unique_fd fd(
937 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700938 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800939 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800940 return false;
941 }
942
Vishnu Naire97d6122018-01-18 13:58:56 -0800943 return (AddZipEntryFromFd(entry_name, fd.get()) == OK);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800944}
945
946/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700947static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800948 return (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) == OK) ? 0 : 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800949}
950
Felipe Leme1d486fe2016-10-14 18:06:47 -0700951void Dumpstate::AddDir(const std::string& dir, bool recursive) {
Felipe Leme678727a2016-09-21 17:22:11 -0700952 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
Felipe Leme46b85da2016-11-21 17:40:45 -0800953 DurationReporter duration_reporter(dir, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700954 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800955}
956
Felipe Leme1d486fe2016-10-14 18:06:47 -0700957bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800958 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Kevin Jeon9bbe0ac2022-05-05 22:05:43 +0000959 size_t flags = ZipWriter::kCompress | ZipWriter::kDefaultCompression;
960 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), flags, ds.now_);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700961 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700962 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700963 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800964 return false;
965 }
966
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700967 err = zip_writer_->WriteBytes(content.c_str(), content.length());
Felipe Leme1d486fe2016-10-14 18:06:47 -0700968 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700969 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700970 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800971 return false;
972 }
973
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700974 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700975 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700976 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800977 return false;
978 }
979
980 return true;
981}
982
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800983static void DoKmsg() {
984 struct stat st;
985 if (!stat(PSTORE_LAST_KMSG, &st)) {
986 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
987 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
988 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
989 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
990 } else {
991 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
992 DumpFile("LAST KMSG", "/proc/last_kmsg");
993 }
994}
995
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800996static void DoKernelLogcat() {
Yao Chenbe3bbc12018-01-17 16:31:10 -0800997 unsigned long timeout_ms = logcat_timeout({"kernel"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800998 RunCommand(
999 "KERNEL LOG",
1000 {"logcat", "-b", "kernel", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1001 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1002}
1003
Nandana Duttdb379fa2019-10-09 16:54:41 +01001004static void DoSystemLogcat(time_t since) {
1005 char since_str[80];
1006 strftime(since_str, sizeof(since_str), "%Y-%m-%d %H:%M:%S.000", localtime(&since));
1007
1008 unsigned long timeout_ms = logcat_timeout({"main", "system", "crash"});
1009 RunCommand("SYSTEM LOG",
1010 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v", "-T",
1011 since_str},
1012 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1013}
1014
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001015static void DoRadioLogcat() {
1016 unsigned long timeout_ms = logcat_timeout({"radio"});
1017 RunCommand(
1018 "RADIO LOG",
1019 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1020 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
1021}
1022
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001023static void DoLogcat() {
Vishnu Nair6921f802017-11-22 09:17:23 -08001024 unsigned long timeout_ms;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001025 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
1026 // calculate timeout
Yao Chenbe3bbc12018-01-17 16:31:10 -08001027 timeout_ms = logcat_timeout({"main", "system", "crash"});
Tony Makae737652017-03-30 17:47:09 +01001028 RunCommand("SYSTEM LOG",
Vishnu Nair6921f802017-11-22 09:17:23 -08001029 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1030 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -08001031 timeout_ms = logcat_timeout({"events"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001032 RunCommand(
1033 "EVENT LOG",
1034 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001035 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Yao Chenbe3bbc12018-01-17 16:31:10 -08001036 timeout_ms = logcat_timeout({"stats"});
1037 RunCommand(
1038 "STATS LOG",
1039 {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001040 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001041 DoRadioLogcat();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001042
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001043 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001044 RunCommand("LAST LOGCAT", {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable",
1045 "-v", "uid", "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001046}
1047
Mike Ma5c267872019-08-21 11:31:34 -07001048static void DumpIncidentReport() {
Mike Ma5c267872019-08-21 11:31:34 -07001049 const std::string path = ds.bugreport_internal_dir_ + "/tmp_incident_report";
1050 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1051 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1052 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1053 if (fd < 0) {
1054 MYLOGE("Could not open %s to dump incident report.\n", path.c_str());
1055 return;
1056 }
Kevin Jeonfa64e642023-07-27 11:36:41 -04001057 RunCommandToFd(fd, "", {"incident", "-u"},
1058 CommandOptions::WithTimeout(PropertiesHelper::IsStrictRun() ? 20 : 120).Build());
Mike Ma5c267872019-08-21 11:31:34 -07001059 bool empty = 0 == lseek(fd, 0, SEEK_END);
1060 if (!empty) {
1061 // Use a different name from "incident.proto"
1062 // /proto/incident.proto is reserved for incident service dump
1063 // i.e. metadata for debugging.
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001064 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "incident_report" + kProtoExt,
1065 path);
1066 } else {
1067 unlink(path.c_str());
Mike Ma5c267872019-08-21 11:31:34 -07001068 }
Mike Ma5c267872019-08-21 11:31:34 -07001069}
1070
Aaron Huang24d215d2022-04-27 18:51:16 +08001071static void DumpNetstatsProto() {
1072 const std::string path = ds.bugreport_internal_dir_ + "/tmp_netstats_proto";
1073 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1074 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1075 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1076 if (fd < 0) {
1077 MYLOGE("Could not open %s to dump netstats proto.\n", path.c_str());
1078 return;
1079 }
1080 RunCommandToFd(fd, "", {"dumpsys", "netstats", "--proto"},
Kevin Jeon2fb3dd62022-09-28 18:48:55 +00001081 CommandOptions::WithTimeout(5).Build());
Aaron Huang24d215d2022-04-27 18:51:16 +08001082 bool empty = 0 == lseek(fd, 0, SEEK_END);
1083 if (!empty) {
1084 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "netstats" + kProtoExt,
1085 path);
1086 } else {
1087 unlink(path.c_str());
1088 }
1089}
1090
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001091static void MaybeAddSystemTraceToZip() {
1092 // This function copies into the .zip the system trace that was snapshotted
Kean Mariottica20f2d2023-12-15 09:34:25 +00001093 // by the early call to MaybeSnapshotSystemTraceAsync(), if any background
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001094 // tracing was happening.
Kean Mariotti853b73a2023-07-27 12:40:30 +00001095 bool system_trace_exists = access(SYSTEM_TRACE_SNAPSHOT, F_OK) == 0;
1096 if (!system_trace_exists) {
Kean Mariottica20f2d2023-12-15 09:34:25 +00001097 // No background trace was happening at the time MaybeSnapshotSystemTraceAsync() was invoked
Kean Mariotti853b73a2023-07-27 12:40:30 +00001098 if (!PropertiesHelper::IsUserBuild()) {
1099 MYLOGI(
1100 "No system traces found. Check for previously uploaded traces by looking for "
1101 "go/trace-uuid in logcat")
1102 }
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001103 return;
1104 }
1105 ds.AddZipEntry(
1106 ZIP_ROOT_DIR + SYSTEM_TRACE_SNAPSHOT,
1107 SYSTEM_TRACE_SNAPSHOT);
1108 android::os::UnlinkAndLogOnError(SYSTEM_TRACE_SNAPSHOT);
1109}
1110
Sunny Goyal35949782019-11-19 15:54:36 -08001111static void DumpVisibleWindowViews() {
Sunny Goyal35949782019-11-19 15:54:36 -08001112 DurationReporter duration_reporter("VISIBLE WINDOW VIEWS");
1113 const std::string path = ds.bugreport_internal_dir_ + "/tmp_visible_window_views";
1114 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1115 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1116 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1117 if (fd < 0) {
1118 MYLOGE("Could not open %s to dump visible views.\n", path.c_str());
1119 return;
1120 }
1121 RunCommandToFd(fd, "", {"cmd", "window", "dump-visible-window-views"},
Kevin Jeon774abde2022-09-28 18:20:43 +00001122 CommandOptions::WithTimeout(10).Build());
Sunny Goyal35949782019-11-19 15:54:36 -08001123 bool empty = 0 == lseek(fd, 0, SEEK_END);
1124 if (!empty) {
1125 ds.AddZipEntry("visible_windows.zip", path);
1126 } else {
1127 MYLOGW("Failed to dump visible windows\n");
1128 }
1129 unlink(path.c_str());
1130}
1131
Jayachandran Ca94c7172017-06-10 15:08:12 -07001132static void DumpIpTablesAsRoot() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001133 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
1134 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +09001135 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001136 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +09001137 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
1138 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
1139 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
1140 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001141}
1142
Woody Lin20767a92022-11-29 15:50:24 +08001143static void DumpShutdownCheckpoints() {
1144 const bool shutdown_checkpoints_dumped = AddDumps(
1145 ds.shutdown_checkpoints_.begin(), ds.shutdown_checkpoints_.end(),
1146 "SHUTDOWN CHECKPOINTS", false /* add_to_zip */);
1147 if (!shutdown_checkpoints_dumped) {
1148 printf("*** NO SHUTDOWN CHECKPOINTS to dump in %s\n\n",
1149 SHUTDOWN_CHECKPOINTS_DIR.c_str());
1150 }
1151}
1152
David Andersond9ba4752018-12-11 18:26:59 -08001153static void DumpDynamicPartitionInfo() {
1154 if (!::android::base::GetBoolProperty("ro.boot.dynamic_partitions", false)) {
1155 return;
1156 }
1157
1158 RunCommand("LPDUMP", {"lpdump", "--all"});
David Anderson6650ade2019-10-02 15:18:59 -07001159 RunCommand("DEVICE-MAPPER", {"gsid", "dump-device-mapper"});
David Andersond9ba4752018-12-11 18:26:59 -08001160}
1161
Chris Morin5a50d482022-02-01 17:41:18 -08001162static void AddAnrTraceDir(const std::string& anr_traces_dir) {
Narayan Kamath8f788292017-05-25 13:20:39 +01001163 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
1164 anr_traces_dir.c_str());
1165
1166 // If we're here, dump_traces_path will always be a temporary file
1167 // (created with mkostemp or similar) that contains dumps taken earlier
1168 // on in the process.
1169 if (dump_traces_path != nullptr) {
Chris Morin5a50d482022-02-01 17:41:18 -08001170 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
1171 dump_traces_path);
1172 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
Narayan Kamath8f788292017-05-25 13:20:39 +01001173
1174 const int ret = unlink(dump_traces_path);
1175 if (ret == -1) {
1176 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
1177 strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -07001178 }
1179 }
1180
Narayan Kamathbd863722017-06-01 18:50:12 +01001181 // Add a specific message for the first ANR Dump.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001182 if (ds.anr_data_.size() > 0) {
Chris Morin5a50d482022-02-01 17:41:18 -08001183 // The "last" ANR will always be present in the body of the main entry.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001184 AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1,
Chris Morin5a50d482022-02-01 17:41:18 -08001185 "VM TRACES AT LAST ANR", false /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001186
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001187 // Historical ANRs are always included as separate entries in the bugreport zip file.
Chris Morin5a50d482022-02-01 17:41:18 -08001188 AddDumps(ds.anr_data_.begin(), ds.anr_data_.end(),
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001189 "HISTORICAL ANR", true /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001190 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +01001191 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
1192 }
Andy Hungd62f7e62024-01-11 15:47:52 -08001193
1194 // Add Java anr traces (such as generated by the Finalizer Watchdog).
1195 AddDumps(ds.anr_trace_data_.begin(), ds.anr_trace_data_.end(), "JAVA ANR TRACES",
1196 true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001197}
1198
1199static void AddAnrTraceFiles() {
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001200 std::string anr_traces_dir = "/data/anr";
Narayan Kamath8f788292017-05-25 13:20:39 +01001201
Chris Morin5a50d482022-02-01 17:41:18 -08001202 AddAnrTraceDir(anr_traces_dir);
Narayan Kamath8f788292017-05-25 13:20:39 +01001203
Makoto Onuki83ec63f2019-01-31 17:08:59 -08001204 RunCommand("ANR FILES", {"ls", "-lt", ANR_DIR});
1205
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001206 // Slow traces for slow operations.
Felipe Lemee184f662016-10-27 10:04:47 -07001207 struct stat st;
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001208 int i = 0;
1209 while (true) {
1210 const std::string slow_trace_path =
1211 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
1212 if (stat(slow_trace_path.c_str(), &st)) {
1213 // No traces file at this index, done with the files.
1214 break;
Felipe Lemee184f662016-10-27 10:04:47 -07001215 }
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001216 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
1217 i++;
Felipe Lemee184f662016-10-27 10:04:47 -07001218 }
1219}
1220
Wei Wang509bb5d2017-06-09 14:42:12 -07001221static void DumpBlockStatFiles() {
1222 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -07001223
Wei Wang1dc1ef52017-06-12 11:28:37 -07001224 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
1225
1226 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001227 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1228 return;
1229 }
1230
1231 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -07001232 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001233 if ((d->d_name[0] == '.')
1234 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1235 || (d->d_name[1] == '\0'))) {
1236 continue;
1237 }
1238 const std::string new_path =
1239 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1240 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1241 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1242 printf("\n");
1243 }
Wei Wang1dc1ef52017-06-12 11:28:37 -07001244 return;
Wei Wang509bb5d2017-06-09 14:42:12 -07001245}
Jayachandran Ca94c7172017-06-10 15:08:12 -07001246
1247static void DumpPacketStats() {
1248 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
Jayachandran Ca94c7172017-06-10 15:08:12 -07001249}
1250
1251static void DumpIpAddrAndRules() {
1252 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
Ray Chencbf278a2023-11-20 07:49:45 +00001253 RunCommand("NETWORK INTERFACES", {"ip", "-s", "link"});
Jayachandran Ca94c7172017-06-10 15:08:12 -07001254 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1255 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1256 RunCommand("IP RULES", {"ip", "rule", "show"});
1257 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1258}
1259
Nandana Dutt5c390032019-03-12 10:52:56 +00001260static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, int priority,
1261 std::chrono::milliseconds timeout,
1262 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001263 auto start = std::chrono::steady_clock::now();
Vishnu Naire97d6122018-01-18 13:58:56 -08001264 sp<android::IServiceManager> sm = defaultServiceManager();
1265 Dumpsys dumpsys(sm.get());
Vishnu Naire97d6122018-01-18 13:58:56 -08001266 Vector<String16> args;
1267 Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
Vishnu Naire97d6122018-01-18 13:58:56 -08001268 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1269 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001270 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001271 std::string path(title);
1272 path.append(" - ").append(String8(service).c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -08001273 size_t bytes_written = 0;
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001274 if (PropertiesHelper::IsDryRun()) {
1275 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1276 dumpsys.writeDumpFooter(STDOUT_FILENO, service, std::chrono::milliseconds(1));
1277 } else {
Devin Mooref492c1a2023-03-15 19:19:03 +00001278 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP | Dumpsys::TYPE_PID |
1279 Dumpsys::TYPE_CLIENTS | Dumpsys::TYPE_THREAD,
Devin Mooreae68df22023-02-24 20:59:51 +00001280 service, args);
1281 if (status == OK) {
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001282 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1283 std::chrono::duration<double> elapsed_seconds;
1284 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH &&
1285 service == String16("meminfo")) {
1286 // Use a longer timeout for meminfo, since 30s is not always enough.
1287 status = dumpsys.writeDump(STDOUT_FILENO, service, 60s,
1288 /* as_proto = */ false, elapsed_seconds,
1289 bytes_written);
1290 } else {
1291 status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
1292 /* as_proto = */ false, elapsed_seconds,
1293 bytes_written);
1294 }
1295 dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
1296 bool dump_complete = (status == OK);
1297 dumpsys.stopDumpThread(dump_complete);
Devin Moorecdfa4602023-03-16 20:49:39 +00001298 } else {
1299 MYLOGE("Failed to start dump thread for service: %s, status: %d",
1300 String8(service).c_str(), status);
Gavin Corkeryfac7e2b2021-07-08 22:39:02 +01001301 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001302 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001303
1304 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1305 std::chrono::steady_clock::now() - start);
1306 if (elapsed_duration > timeout) {
1307 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1308 elapsed_duration.count());
1309 break;
1310 }
1311 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001312 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001313}
1314
Vishnu Nair64afc022018-02-01 15:29:34 -08001315static void RunDumpsysText(const std::string& title, int priority,
1316 std::chrono::milliseconds timeout,
1317 std::chrono::milliseconds service_timeout) {
1318 DurationReporter duration_reporter(title);
1319 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1320 fsync(STDOUT_FILENO);
1321 RunDumpsysTextByPriority(title, priority, timeout, service_timeout);
1322}
1323
1324/* Dump all services registered with Normal or Default priority. */
Nandana Dutt5c390032019-03-12 10:52:56 +00001325static Dumpstate::RunStatus RunDumpsysTextNormalPriority(const std::string& title,
1326 std::chrono::milliseconds timeout,
1327 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001328 DurationReporter duration_reporter(title);
1329 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1330 fsync(STDOUT_FILENO);
1331 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout,
1332 service_timeout);
Nandana Dutt5c390032019-03-12 10:52:56 +00001333
1334 RETURN_IF_USER_DENIED_CONSENT();
1335
1336 return RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1337 service_timeout);
Vishnu Nair64afc022018-02-01 15:29:34 -08001338}
1339
Nandana Dutt5c390032019-03-12 10:52:56 +00001340static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priority,
1341 std::chrono::milliseconds timeout,
1342 std::chrono::milliseconds service_timeout) {
Vishnu Naire97d6122018-01-18 13:58:56 -08001343 sp<android::IServiceManager> sm = defaultServiceManager();
1344 Dumpsys dumpsys(sm.get());
1345 Vector<String16> args;
1346 Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
1347 DurationReporter duration_reporter(title);
1348
1349 auto start = std::chrono::steady_clock::now();
1350 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
1351 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001352 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001353 std::string path(kProtoPath);
1354 path.append(String8(service).c_str());
1355 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
1356 path.append("_CRITICAL");
1357 } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
1358 path.append("_HIGH");
1359 }
1360 path.append(kProtoExt);
Steven Morelandcbd69fc2021-07-20 20:45:43 +00001361 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP, service, args);
Vishnu Naire97d6122018-01-18 13:58:56 -08001362 if (status == OK) {
1363 status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
1364 bool dumpTerminated = (status == OK);
1365 dumpsys.stopDumpThread(dumpTerminated);
1366 }
1367 ZipWriter::FileEntry file_entry;
1368 ds.zip_writer_->GetLastEntry(&file_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -08001369
1370 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1371 std::chrono::steady_clock::now() - start);
1372 if (elapsed_duration > timeout) {
1373 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1374 elapsed_duration.count());
1375 break;
1376 }
1377 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001378 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001379}
1380
Nandana Dutta7db6342018-11-21 14:53:34 +00001381// Runs dumpsys on services that must dump first and will take less than 100ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001382static Dumpstate::RunStatus RunDumpsysCritical() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001383 RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1384 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Nandana Dutt5c390032019-03-12 10:52:56 +00001385
1386 RETURN_IF_USER_DENIED_CONSENT();
1387
1388 return RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1389 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Vishnu Nair780b1282017-10-10 13:57:24 -07001390}
1391
1392// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001393static Dumpstate::RunStatus RunDumpsysHigh() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001394 // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
1395 // high priority. Reduce timeout once they are able to dump in a shorter time or
1396 // moved to a parallel task.
1397 RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1398 /* timeout= */ 90s, /* service_timeout= */ 30s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001399
1400 RETURN_IF_USER_DENIED_CONSENT();
1401
1402 return RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1403 /* timeout= */ 5s, /* service_timeout= */ 1s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001404}
1405
1406// Runs dumpsys on services that must dump but can take up to 10s to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001407static Dumpstate::RunStatus RunDumpsysNormal() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001408 RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001409
1410 RETURN_IF_USER_DENIED_CONSENT();
1411
1412 return RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1413 /* timeout= */ 90s, /* service_timeout= */ 10s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001414}
1415
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001416/*
1417 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1418 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1419 * if it's not running in the parallel task.
1420 */
1421static void DumpHals(int out_fd = STDOUT_FILENO) {
Yifan Hong30528a22020-08-07 18:24:06 -07001422 RunCommand("HARDWARE HALS", {"lshal", "--all", "--types=all"},
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001423 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build(),
1424 false, out_fd);
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001425
Steven Moreland44cd9482018-01-04 16:24:13 -08001426 using android::hidl::manager::V1_0::IServiceManager;
1427 using android::hardware::defaultServiceManager;
1428
1429 sp<IServiceManager> sm = defaultServiceManager();
1430 if (sm == nullptr) {
1431 MYLOGE("Could not retrieve hwservicemanager to dump hals.\n");
1432 return;
1433 }
1434
1435 auto ret = sm->list([&](const auto& interfaces) {
1436 for (const std::string& interface : interfaces) {
1437 std::string cleanName = interface;
Steven Morelandc6b1fc22023-07-26 23:53:58 +00001438 std::replace_if(
1439 cleanName.begin(), cleanName.end(),
1440 [](char c) {
1441 return !isalnum(c) && std::string("@-_.").find(c) == std::string::npos;
1442 },
1443 '_');
Nandana Dutt979388e2018-11-30 16:48:55 +00001444 const std::string path = ds.bugreport_internal_dir_ + "/lshal_debug_" + cleanName;
Steven Moreland44cd9482018-01-04 16:24:13 -08001445
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001446 bool empty = false;
Steven Moreland44cd9482018-01-04 16:24:13 -08001447 {
1448 auto fd = android::base::unique_fd(
1449 TEMP_FAILURE_RETRY(open(path.c_str(),
1450 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1451 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1452 if (fd < 0) {
1453 MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str());
1454 continue;
1455 }
1456 RunCommandToFd(fd,
1457 "",
Steven Morelandc81cd3c2018-01-18 14:36:26 -08001458 {"lshal", "debug", "-E", interface},
Steven Moreland44cd9482018-01-04 16:24:13 -08001459 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1460
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001461 empty = 0 == lseek(fd, 0, SEEK_END);
Steven Moreland44cd9482018-01-04 16:24:13 -08001462 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001463 if (!empty) {
1464 ds.EnqueueAddZipEntryAndCleanupIfNeeded("lshal-debug/" + cleanName + ".txt",
1465 path);
1466 } else {
1467 unlink(path.c_str());
1468 }
Steven Moreland44cd9482018-01-04 16:24:13 -08001469 }
1470 });
1471
1472 if (!ret.isOk()) {
1473 MYLOGE("Could not list hals from hwservicemanager.\n");
1474 }
1475}
1476
Devin Moore8df81bb2022-06-08 22:47:02 +00001477// Dump all of the files that make up the vendor interface.
1478// See the files listed in dumpFileList() for the latest list of files.
1479static void DumpVintf() {
Devin Moore16271d92022-09-22 18:28:48 +00001480
1481 const std::string sku = android::base::GetProperty("ro.boot.product.hardware.sku", "");
1482 const auto vintfFiles = android::vintf::details::dumpFileList(sku);
Devin Moore8df81bb2022-06-08 22:47:02 +00001483 for (const auto vintfFile : vintfFiles) {
1484 struct stat st;
1485 if (stat(vintfFile.c_str(), &st) == 0) {
1486 if (S_ISDIR(st.st_mode)) {
1487 ds.AddDir(vintfFile, true /* recursive */);
1488 } else {
1489 ds.EnqueueAddZipEntryAndCleanupIfNeeded(ZIP_ROOT_DIR + vintfFile,
1490 vintfFile);
1491 }
1492 }
1493 }
1494}
1495
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001496static void DumpExternalFragmentationInfo() {
1497 struct stat st;
1498 if (stat("/proc/buddyinfo", &st) != 0) {
1499 MYLOGE("Unable to dump external fragmentation info\n");
1500 return;
1501 }
1502
1503 printf("------ EXTERNAL FRAGMENTATION INFO ------\n");
1504 std::ifstream ifs("/proc/buddyinfo");
1505 auto unusable_index_regex = std::regex{"Node\\s+([0-9]+),\\s+zone\\s+(\\S+)\\s+(.*)"};
1506 for (std::string line; std::getline(ifs, line);) {
1507 std::smatch match_results;
1508 if (std::regex_match(line, match_results, unusable_index_regex)) {
1509 std::stringstream free_pages(std::string{match_results[3]});
1510 std::vector<int> free_pages_per_order(std::istream_iterator<int>{free_pages},
1511 std::istream_iterator<int>());
1512
1513 int total_free_pages = 0;
1514 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1515 total_free_pages += (free_pages_per_order[i] * std::pow(2, i));
1516 }
1517
1518 printf("Node %s, zone %8s", match_results[1].str().c_str(),
1519 match_results[2].str().c_str());
1520
1521 int usable_free_pages = total_free_pages;
1522 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1523 auto unusable_index = (total_free_pages - usable_free_pages) /
1524 static_cast<double>(total_free_pages);
1525 printf(" %5.3f", unusable_index);
1526 usable_free_pages -= (free_pages_per_order[i] * std::pow(2, i));
1527 }
1528
1529 printf("\n");
1530 }
1531 }
1532 printf("\n");
1533}
1534
mhasankd451a472020-05-26 18:02:39 -07001535static void DumpstateLimitedOnly() {
EdenSue8fe4522023-11-20 15:37:23 +08001536 // Trimmed-down version of dumpstate to only include a allowlisted
mhasankd451a472020-05-26 18:02:39 -07001537 // set of logs (system log, event log, and system server / system app
1538 // crashes, and networking logs). See b/136273873 and b/138459828
1539 // for context.
1540 DurationReporter duration_reporter("DUMPSTATE");
1541 unsigned long timeout_ms;
1542 // calculate timeout
1543 timeout_ms = logcat_timeout({"main", "system", "crash"});
1544 RunCommand("SYSTEM LOG",
1545 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1546 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1547 timeout_ms = logcat_timeout({"events"});
1548 RunCommand(
1549 "EVENT LOG",
1550 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1551 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1552
1553 printf("========================================================\n");
1554 printf("== Networking Service\n");
1555 printf("========================================================\n");
1556
1557 RunDumpsys("DUMPSYS NETWORK_SERVICE_LIMITED", {"wifi", "-a"},
1558 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hugo Benichiaa162682020-10-30 23:28:56 +09001559 RunDumpsys("DUMPSYS CONNECTIVITY REQUESTS", {"connectivity", "requests"},
1560 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
mhasankd451a472020-05-26 18:02:39 -07001561
1562 printf("========================================================\n");
Chuwei Hecc54a252024-07-25 15:18:36 +09001563 printf("== Networking Policy\n");
1564 printf("========================================================\n");
1565
1566 RunDumpsys("DUMPSYS NETWORK POLICY", {"netpolicy"}, CommandOptions::WithTimeout(90).Build(),
1567 SEC_TO_MSEC(10));
1568
1569 printf("========================================================\n");
mhasankd451a472020-05-26 18:02:39 -07001570 printf("== Dropbox crashes\n");
1571 printf("========================================================\n");
1572
1573 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1574 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1575
Bryan Yuefb85d92024-02-02 13:37:06 +00001576
1577 printf("========================================================\n");
1578 printf("== ANR Traces\n");
1579 printf("========================================================\n");
1580
Bryan Yucf038cf2024-05-08 09:25:25 +00001581 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX);
Bryan Yuefb85d92024-02-02 13:37:06 +00001582 AddAnrTraceFiles();
1583
mhasankd451a472020-05-26 18:02:39 -07001584 printf("========================================================\n");
1585 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1586 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1587 printf("========================================================\n");
1588 printf("== dumpstate: done (id %d)\n", ds.id_);
1589 printf("========================================================\n");
1590}
1591
Rhed Jaoe017f982020-07-21 17:58:41 +08001592/*
1593 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1594 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1595 * if it's not running in the parallel task.
1596 */
1597static void DumpCheckins(int out_fd = STDOUT_FILENO) {
1598 dprintf(out_fd, "========================================================\n");
1599 dprintf(out_fd, "== Checkins\n");
1600 dprintf(out_fd, "========================================================\n");
1601
1602 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"}, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001603 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"}, out_fd);
1604 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"}, out_fd);
1605 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"}, out_fd);
1606 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"}, out_fd);
1607}
1608
1609/*
1610 * Runs dumpsys on activity service to dump all application activities, services
1611 * and providers in the device.
1612 *
1613 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1614 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1615 * if it's not running in the parallel task.
1616 */
1617static void DumpAppInfos(int out_fd = STDOUT_FILENO) {
1618 dprintf(out_fd, "========================================================\n");
1619 dprintf(out_fd, "== Running Application Activities\n");
1620 dprintf(out_fd, "========================================================\n");
1621
1622 // The following dumpsys internally collects output from running apps, so it can take a long
1623 // time. So let's extend the timeout.
1624
1625 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1626
1627 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1628
1629 dprintf(out_fd, "========================================================\n");
1630 dprintf(out_fd, "== Running Application Services (platform)\n");
1631 dprintf(out_fd, "========================================================\n");
1632
1633 RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
1634 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1635
1636 dprintf(out_fd, "========================================================\n");
1637 dprintf(out_fd, "== Running Application Services (non-platform)\n");
1638 dprintf(out_fd, "========================================================\n");
1639
1640 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1641 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1642
1643 dprintf(out_fd, "========================================================\n");
1644 dprintf(out_fd, "== Running Application Providers (platform)\n");
1645 dprintf(out_fd, "========================================================\n");
1646
1647 RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
Rhed Jaob049f182021-01-11 21:08:43 +08001648 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001649
1650 dprintf(out_fd, "========================================================\n");
1651 dprintf(out_fd, "== Running Application Providers (non-platform)\n");
1652 dprintf(out_fd, "========================================================\n");
1653
1654 RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1655 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1656}
1657
Nandana Dutt5c390032019-03-12 10:52:56 +00001658// Dumps various things. Returns early with status USER_CONSENT_DENIED if user denies consent
1659// via the consent they are shown. Ignores other errors that occur while running various
1660// commands. The consent checking is currently done around long running tasks, which happen to
1661// be distributed fairly evenly throughout the function.
Kean Mariotti306633e2022-09-05 16:30:47 +00001662Dumpstate::RunStatus Dumpstate::dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001663 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001664
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001665 // Enqueue slow functions into the thread pool, if the parallel run is enabled.
Aaron Huang24d215d2022-04-27 18:51:16 +08001666 std::future<std::string> dump_hals, dump_incident_report, dump_board, dump_checkins,
Kean Mariottica20f2d2023-12-15 09:34:25 +00001667 dump_netstats_report;
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001668 if (ds.dump_pool_) {
1669 // Pool was shutdown in DumpstateDefaultAfterCritical method in order to
Kean Mariotti306633e2022-09-05 16:30:47 +00001670 // drop root user. Restarts it.
1671 ds.dump_pool_->start(/* thread_counts = */3);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001672
Chris Morinbc223142022-02-04 14:17:11 -08001673 dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
1674 dump_incident_report = ds.dump_pool_->enqueueTask(
1675 DUMP_INCIDENT_REPORT_TASK, &DumpIncidentReport);
Aaron Huang24d215d2022-04-27 18:51:16 +08001676 dump_netstats_report = ds.dump_pool_->enqueueTask(
1677 DUMP_NETSTATS_PROTO_TASK, &DumpNetstatsProto);
Chris Morinbc223142022-02-04 14:17:11 -08001678 dump_board = ds.dump_pool_->enqueueTaskWithFd(
1679 DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
1680 dump_checkins = ds.dump_pool_->enqueueTaskWithFd(DUMP_CHECKINS_TASK, &DumpCheckins, _1);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001681 }
1682
Nandana Dutt5c390032019-03-12 10:52:56 +00001683 // Dump various things. Note that anything that takes "long" (i.e. several seconds) should
1684 // check intermittently (if it's intrerruptable like a foreach on pids) and/or should be wrapped
1685 // in a consent check (via RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK).
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001686 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001687 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001688 DumpBlockStatFiles();
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001689 DumpFile("MEMORY INFO", "/proc/meminfo");
1690 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001691 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001692
Kevin Jeon947922b2022-09-21 00:29:18 +00001693 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "BUGREPORT_PROCDUMP", {"bugreport_procdump"},
1694 CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001695
Sunny Goyal35949782019-11-19 15:54:36 -08001696 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpVisibleWindowViews);
1697
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001698 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1699 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1700 DumpFile("SLAB INFO", "/proc/slabinfo");
1701 DumpFile("ZONEINFO", "/proc/zoneinfo");
1702 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1703 DumpFile("BUDDYINFO", "/proc/buddyinfo");
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001704 DumpExternalFragmentationInfo();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001705
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001706 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001707
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001708 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001709 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001710
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001711 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001712 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_hals));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001713 } else {
1714 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_HALS_TASK, DumpHals);
1715 }
Steven Moreland81b429e2017-01-31 19:50:46 -08001716
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001717 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001718 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001719 struct stat s;
1720 if (stat("/proc/modules", &s) != 0) {
1721 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1722 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001723 RunCommand("LSMOD", {"lsmod"});
Woody Linc198f252021-05-04 16:37:11 +08001724 RunCommand("MODULES INFO",
1725 {"sh", "-c", "cat /proc/modules | cut -d' ' -f1 | "
1726 " while read MOD ; do echo modinfo:$MOD ; modinfo $MOD ; "
1727 "done"}, CommandOptions::AS_ROOT);
Felipe Lemee4eca582016-06-10 17:48:08 -07001728 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001729
Tom Cherryb87dbfa2020-07-28 11:28:53 -07001730 if (android::base::GetBoolProperty("ro.logd.kernel", false)) {
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001731 DoKernelLogcat();
1732 } else {
1733 do_dmesg();
1734 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001735
Devin Moore8df81bb2022-06-08 22:47:02 +00001736 DumpVintf();
1737
Felipe Lemef0292972016-11-22 13:57:05 -08001738 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001739
Jeff Brown1dc94e32014-09-11 14:15:27 -07001740 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001741 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001742
Jack Yu5a6b2e22020-08-14 18:13:35 +08001743 /* Dump Nfc NCI logs */
1744 ds.AddDir("/data/misc/nfc/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001745
Paul Chang0d2aad72020-02-13 20:04:03 +08001746 if (ds.options_->do_screenshot && !ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001747 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001748 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001749 }
1750
Felipe Lemee184f662016-10-27 10:04:47 -07001751 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001752
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001753 MaybeAddSystemTraceToZip();
1754
Narayan Kamath8f788292017-05-25 13:20:39 +01001755 // NOTE: tombstones are always added as separate entries in the zip archive
1756 // and are not interspersed with the main report.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001757 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
Narayan Kamathbd863722017-06-01 18:50:12 +01001758 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001759 if (!tombstones_dumped) {
1760 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001761 }
1762
Jayachandran Ca94c7172017-06-10 15:08:12 -07001763 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001764
Lorenzo Colitti807f2dd2022-05-27 12:48:37 +09001765 RunDumpsys("EBPF MAP STATS", {"connectivity", "trafficcontroller"});
Chenbo Feng276a3b62018-08-07 11:44:49 -07001766
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001767 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001768
Woody Lin20767a92022-11-29 15:50:24 +08001769 DumpShutdownCheckpoints();
1770
Jayachandran Ca94c7172017-06-10 15:08:12 -07001771 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001772
1773 dump_route_tables();
1774
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001775 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1776 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1777 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001778
Nandana Dutt5c390032019-03-12 10:52:56 +00001779 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysHigh);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001780
Chiachang Wang668ede42021-05-17 17:14:20 +08001781 // The dump mechanism in connectivity is refactored due to modularization work. Connectivity can
1782 // only register with a default priority(NORMAL priority). Dumpstate has to call connectivity
1783 // dump with priority parameters to dump high priority information.
1784 RunDumpsys("SERVICE HIGH connectivity", {"connectivity", "--dump-priority", "HIGH"},
1785 CommandOptions::WithTimeout(10).Build());
1786
Elliott Hughes23ccc622017-02-28 10:14:22 -08001787 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001788
Joe Onoratod38bc3a2023-06-29 15:48:28 -07001789 DumpFile("SYSTEM BUILD-TIME RELEASE FLAGS", "/system/etc/build_flags.json");
1790 DumpFile("SYSTEM_EXT BUILD-TIME RELEASE FLAGS", "/system_ext/etc/build_flags.json");
1791 DumpFile("PRODUCT BUILD-TIME RELEASE FLAGS", "/product/etc/build_flags.json");
1792 DumpFile("VENDOR BUILD-TIME RELEASE FLAGS", "/vendor/etc/build_flags.json");
1793
MÃ¥rten Kongstad5ad813f2023-09-28 10:09:18 +02001794 RunCommand("ACONFIG FLAGS", {PRINT_FLAGS},
1795 CommandOptions::WithTimeout(10).Always().DropRoot().Build());
Ted Bauerf6d61b82024-09-13 19:57:19 +00001796 RunCommand("ACONFIG FLAGS DUMP", {AFLAGS, "list"},
1797 CommandOptions::WithTimeout(10).Always().AsRootIfAvailable().Build());
1798 RunCommand("WHICH ACONFIG FLAG STORAGE", {AFLAGS, "which-backing"},
1799 CommandOptions::WithTimeout(10).Always().AsRootIfAvailable().Build());
Joe Onoratod38bc3a2023-06-29 15:48:28 -07001800
Jin Qianf334d662017-10-10 14:41:37 -07001801 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001802
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001803 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001804
Colin Crossf45fa6b2012-03-26 12:38:26 -07001805 /* Binder state is expensive to look at as it uses a lot of memory. */
Hridya Valsaraju920ba712020-02-09 16:27:01 -08001806 std::string binder_logs_dir = access("/dev/binderfs/binder_logs", R_OK) ?
1807 "/sys/kernel/debug/binder" : "/dev/binderfs/binder_logs";
1808
1809 DumpFile("BINDER FAILED TRANSACTION LOG", binder_logs_dir + "/failed_transaction_log");
1810 DumpFile("BINDER TRANSACTION LOG", binder_logs_dir + "/transaction_log");
1811 DumpFile("BINDER TRANSACTIONS", binder_logs_dir + "/transactions");
1812 DumpFile("BINDER STATS", binder_logs_dir + "/stats");
1813 DumpFile("BINDER STATE", binder_logs_dir + "/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001814
Yifan Hongd90cc652020-02-08 16:52:02 -08001815 ds.AddDir(SNAPSHOTCTL_LOG_DIR, false);
1816
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001817 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001818 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_board));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001819 } else {
1820 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
1821 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001822
Steven Moreland7440ddb2016-12-15 16:13:39 -08001823 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001824 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1825 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001826 // su does not exist on user builds, so try running without it.
1827 // This way any implementations of vril-dump that do not require
1828 // root can run on user builds.
1829 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001830 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001831 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001832 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001833 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001834 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001835 }
1836
Felipe Lemed8b94e52016-12-08 10:21:44 -08001837 printf("========================================================\n");
1838 printf("== Android Framework Services\n");
1839 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001840
Nandana Dutt5c390032019-03-12 10:52:56 +00001841 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001842
Jack He91ff2fe2021-02-18 18:23:43 -08001843 /* Dump Bluetooth HCI logs after getting bluetooth_manager dumpsys */
1844 ds.AddDir("/data/misc/bluetooth/logs", true);
1845
Rhed Jaoe017f982020-07-21 17:58:41 +08001846 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001847 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_checkins));
Rhed Jaoe017f982020-07-21 17:58:41 +08001848 } else {
1849 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_CHECKINS_TASK, DumpCheckins);
1850 }
Dianne Hackborn02bea972013-06-26 18:59:09 -07001851
Rhed Jaoc5f7ec32020-12-22 22:11:08 +08001852 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpAppInfos);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001853
Adrian Roos8b397ab2017-04-04 16:35:44 -07001854 printf("========================================================\n");
1855 printf("== Dropbox crashes\n");
1856 printf("========================================================\n");
1857
1858 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1859 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1860
Felipe Lemed8b94e52016-12-08 10:21:44 -08001861 printf("========================================================\n");
1862 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1863 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1864 printf("========================================================\n");
1865 printf("== dumpstate: done (id %d)\n", ds.id_);
1866 printf("========================================================\n");
Bookatz38472142018-09-28 10:20:24 -07001867
1868 printf("========================================================\n");
1869 printf("== Obtaining statsd metadata\n");
1870 printf("========================================================\n");
1871 // This differs from the usual dumpsys stats, which is the stats report data.
1872 RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
Mike Ma5c267872019-08-21 11:31:34 -07001873
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +09001874 // Add linker configuration directory
1875 ds.AddDir(LINKERCONFIG_DIR, true);
1876
Li Li830179f2022-01-04 12:53:29 -08001877 /* Dump frozen cgroupfs */
1878 dump_frozen_cgroupfs();
Li Li2eedd412021-06-30 15:11:53 -07001879
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001880 if (ds.dump_pool_) {
Aaron Huang24d215d2022-04-27 18:51:16 +08001881 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_netstats_report));
1882 } else {
1883 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_NETSTATS_PROTO_TASK,
1884 DumpNetstatsProto);
1885 }
1886
1887 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001888 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_incident_report));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001889 } else {
1890 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_INCIDENT_REPORT_TASK,
1891 DumpIncidentReport);
1892 }
Mike Ma5c267872019-08-21 11:31:34 -07001893
Kean Mariotti306633e2022-09-05 16:30:47 +00001894 MaybeAddUiTracesToZip();
1895
Nandana Dutt5c390032019-03-12 10:52:56 +00001896 return Dumpstate::RunStatus::OK;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001897}
1898
Nandana Dutt5c390032019-03-12 10:52:56 +00001899/*
1900 * Dumps state for the default case; drops root after it's no longer necessary.
1901 *
1902 * Returns RunStatus::OK if everything went fine.
1903 * Returns RunStatus::ERROR if there was an error.
1904 * Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport
1905 * with the caller.
1906 */
Jichao Lie89d9c12019-11-21 19:02:51 -08001907Dumpstate::RunStatus Dumpstate::DumpstateDefaultAfterCritical() {
Nandana Duttdb379fa2019-10-09 16:54:41 +01001908 // Capture first logcat early on; useful to take a snapshot before dumpstate logs take over the
1909 // buffer.
1910 DoLogcat();
1911 // Capture timestamp after first logcat to use in next logcat
1912 time_t logcat_ts = time(nullptr);
1913
Nandana Dutt4be45d12018-09-26 15:04:23 +01001914 /* collect stack traces from Dalvik and native processes (needs root) */
Chris Morinbc223142022-02-04 14:17:11 -08001915 std::future<std::string> dump_traces;
Rhed Jao5377d792020-07-16 17:37:39 +08001916 if (dump_pool_) {
1917 RETURN_IF_USER_DENIED_CONSENT();
1918 // One thread is enough since we only need to enqueue DumpTraces here.
1919 dump_pool_->start(/* thread_counts = */1);
1920
1921 // DumpTraces takes long time, post it to the another thread in the
1922 // pool, if pool is available
Chris Morinbc223142022-02-04 14:17:11 -08001923 dump_traces = dump_pool_->enqueueTask(
1924 DUMP_TRACES_TASK, &Dumpstate::DumpTraces, &ds, &dump_traces_path);
Rhed Jao5377d792020-07-16 17:37:39 +08001925 } else {
1926 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_TRACES_TASK, ds.DumpTraces,
1927 &dump_traces_path);
1928 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001929
1930 /* Run some operations that require root. */
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001931 if (!PropertiesHelper::IsDryRun()) {
Chris Morinc2cba7a2022-02-01 17:06:50 -08001932 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX);
1933 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX);
Andy Hungd62f7e62024-01-11 15:47:52 -08001934 ds.anr_trace_data_ = GetDumpFds(ANR_DIR, ANR_TRACE_FILE_PREFIX);
Woody Lin20767a92022-11-29 15:50:24 +08001935 ds.shutdown_checkpoints_ = GetDumpFds(
1936 SHUTDOWN_CHECKPOINTS_DIR, SHUTDOWN_CHECKPOINTS_FILE_PREFIX);
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001937 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001938
1939 ds.AddDir(RECOVERY_DIR, true);
1940 ds.AddDir(RECOVERY_DATA_DIR, true);
1941 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
Kelvin Zhang6eaa0f92022-09-12 09:29:19 -07001942 ds.AddDir(UPDATE_ENGINE_PREF_DIR, true);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001943 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1944 if (!PropertiesHelper::IsUserBuild()) {
1945 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1946 ds.AddDir(PROFILE_DATA_DIR_REF, true);
Calin Juravlef84d3692020-04-28 15:31:12 -07001947 ds.AddZipEntry(ZIP_ROOT_DIR + PACKAGE_DEX_USE_LIST, PACKAGE_DEX_USE_LIST);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001948 }
Jerry Changa1df8a92020-01-02 16:03:39 +08001949 ds.AddDir(PREREBOOT_DATA_DIR, false);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001950 add_mountinfo();
Peter Collingbourne78aa2942023-02-15 14:50:31 -08001951 for (const char* path : {"/proc/cpuinfo", "/proc/meminfo"}) {
1952 ds.AddZipEntry(ZIP_ROOT_DIR + path, path);
1953 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001954 DumpIpTablesAsRoot();
David Andersond9ba4752018-12-11 18:26:59 -08001955 DumpDynamicPartitionInfo();
Yifan Hong3945e1b2019-10-29 12:59:23 -07001956 ds.AddDir(OTA_METADATA_DIR, true);
Jeff Sharkey9df29d52023-02-06 14:26:30 -07001957 if (!PropertiesHelper::IsUserBuild()) {
1958 // Include dropbox entry files inside ZIP, but exclude
1959 // noisy WTF and StrictMode entries
1960 dump_files("", DROPBOX_DIR, skip_wtf_strictmode, _add_file_from_fd);
1961 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001962
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001963 // Capture any IPSec policies in play. No keys are exposed here.
Nandana Dutt4be45d12018-09-26 15:04:23 +01001964 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1965
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001966 // Dump IPsec stats. No keys are exposed here.
1967 DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
1968
Nandana Dutt4be45d12018-09-26 15:04:23 +01001969 // Run ss as root so we can see socket marks.
1970 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1971
1972 // Run iotop as root to show top 100 IO threads
1973 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1974
Erick Reyese68df822019-02-11 14:46:36 -08001975 // Gather shared memory buffer info if the product implements it
Hridya Valsaraju1da80c52021-01-09 22:10:11 -08001976 RunCommand("Dmabuf dump", {"dmabuf_dump"});
1977 RunCommand("Dmabuf per-buffer/per-exporter/per-device stats", {"dmabuf_dump", "-b"});
Erick Reyese68df822019-02-11 14:46:36 -08001978
Minchan Kim22c6a1e2019-09-30 15:58:10 -07001979 DumpFile("PSI cpu", "/proc/pressure/cpu");
1980 DumpFile("PSI memory", "/proc/pressure/memory");
1981 DumpFile("PSI io", "/proc/pressure/io");
1982
Steven Moreland9379c462023-12-21 02:04:27 +00001983 ds.AddZipEntry(ZIP_ROOT_DIR + KERNEL_CONFIG, KERNEL_CONFIG);
1984
MÃ¥rten Kongstad60195a72022-09-20 14:14:20 +02001985 RunCommand("SDK EXTENSIONS", {SDK_EXT_INFO, "--dump"},
1986 CommandOptions::WithTimeout(10).Always().DropRoot().Build());
1987
Nattharat Jariyanuntanaetb250cae2024-05-15 07:48:19 +00001988 // Dump UWB UCI logs here because apexdata requires root access
1989 ds.AddDir(UWB_LOG_DIR, true);
1990
Rhed Jao5377d792020-07-16 17:37:39 +08001991 if (dump_pool_) {
1992 RETURN_IF_USER_DENIED_CONSENT();
Chris Morinbc223142022-02-04 14:17:11 -08001993 WaitForTask(std::move(dump_traces));
Rhed Jao5377d792020-07-16 17:37:39 +08001994
Chris Morinbc223142022-02-04 14:17:11 -08001995 // Current running thread in the pool is the root user also. Delete
1996 // the pool and make a new one later to ensure none of threads in the pool are root.
1997 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao5377d792020-07-16 17:37:39 +08001998 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001999 if (!DropRootUser()) {
Nandana Dutt5c390032019-03-12 10:52:56 +00002000 return Dumpstate::RunStatus::ERROR;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002001 }
2002
Nandana Dutt5c390032019-03-12 10:52:56 +00002003 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttdb379fa2019-10-09 16:54:41 +01002004 Dumpstate::RunStatus status = dumpstate();
2005 // Capture logcat since the last time we did it.
2006 DoSystemLogcat(logcat_ts);
2007 return status;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002008}
2009
Rhed Jaob5685b32020-08-14 17:19:17 +08002010// Common states for telephony and wifi which are needed to be collected before
2011// dumpstate drop the root user.
2012static void DumpstateRadioAsRoot() {
2013 DumpIpTablesAsRoot();
2014 ds.AddDir(LOGPERSIST_DATA_DIR, false);
2015}
2016
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002017// This method collects common dumpsys for telephony and wifi. Typically, wifi
2018// reports are fine to include all information, but telephony reports on user
2019// builds need to strip some content (see DumpstateTelephonyOnly).
2020static void DumpstateRadioCommon(bool include_sensitive_info = true) {
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002021 // We need to be picky about some stuff for telephony reports on user builds.
2022 if (!include_sensitive_info) {
2023 // Only dump the radio log buffer (other buffers and dumps contain too much unrelated info).
2024 DoRadioLogcat();
2025 } else {
Rhed Jaob5685b32020-08-14 17:19:17 +08002026 // DumpHals takes long time, post it to the another thread in the pool,
2027 // if pool is available.
Chris Morinbc223142022-02-04 14:17:11 -08002028 std::future<std::string> dump_hals;
Rhed Jaob5685b32020-08-14 17:19:17 +08002029 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002030 dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
Rhed Jaob5685b32020-08-14 17:19:17 +08002031 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002032 // Contains various system properties and process startup info.
2033 do_dmesg();
2034 // Logs other than the radio buffer may contain package/component names and potential PII.
2035 DoLogcat();
2036 // Too broad for connectivity problems.
2037 DoKmsg();
Rhed Jaob5685b32020-08-14 17:19:17 +08002038 // DumpHals contains unrelated hardware info (camera, NFC, biometrics, ...).
2039 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002040 WaitForTask(std::move(dump_hals));
Rhed Jaob5685b32020-08-14 17:19:17 +08002041 } else {
2042 RUN_SLOW_FUNCTION_AND_LOG(DUMP_HALS_TASK, DumpHals);
2043 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002044 }
2045
Jayachandran Ca94c7172017-06-10 15:08:12 -07002046 DumpPacketStats();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002047 DumpIpAddrAndRules();
2048 dump_route_tables();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002049 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
2050 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08002051}
2052
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002053// We use "telephony" here for legacy reasons, though this now really means "connectivity" (cellular
2054// + wifi + networking). This method collects dumpsys for connectivity debugging only. General rules
2055// for what can be included on user builds: all reported information MUST directly relate to
2056// connectivity debugging or customer support and MUST NOT contain unrelated personally identifiable
2057// information. This information MUST NOT identify user-installed packages (UIDs are OK, package
2058// names are not), and MUST NOT contain logs of user application traffic.
2059// TODO(b/148168577) rename this and other related fields/methods to "connectivity" instead.
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08002060static void DumpstateTelephonyOnly(const std::string& calling_package) {
mukesh agrawal253dad42018-01-23 21:59:59 -08002061 DurationReporter duration_reporter("DUMPSTATE");
Jichao Lie89d9c12019-11-21 19:02:51 -08002062
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002063 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
mukesh agrawal253dad42018-01-23 21:59:59 -08002064
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002065 const bool include_sensitive_info = !PropertiesHelper::IsUserBuild();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002066
Rhed Jaob5685b32020-08-14 17:19:17 +08002067 DumpstateRadioAsRoot();
2068 if (!DropRootUser()) {
2069 return;
2070 }
2071
2072 // Starts thread pool after the root user is dropped, and two additional threads
2073 // are created for DumpHals in the DumpstateRadioCommon and DumpstateBoard.
Chris Morinbc223142022-02-04 14:17:11 -08002074 std::future<std::string> dump_board;
Rhed Jaob5685b32020-08-14 17:19:17 +08002075 if (ds.dump_pool_) {
2076 ds.dump_pool_->start(/*thread_counts =*/2);
2077
2078 // DumpstateBoard takes long time, post it to the another thread in the pool,
2079 // if pool is available.
Chris Morinbc223142022-02-04 14:17:11 -08002080 dump_board = ds.dump_pool_->enqueueTaskWithFd(
2081 DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
Rhed Jaob5685b32020-08-14 17:19:17 +08002082 }
2083
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002084 DumpstateRadioCommon(include_sensitive_info);
2085
2086 if (include_sensitive_info) {
2087 // Contains too much unrelated PII, and given the unstructured nature of sysprops, we can't
2088 // really cherrypick all of the connectivity-related ones. Apps generally have no business
2089 // reading these anyway, and there should be APIs to supply the info in a more app-friendly
2090 // way.
2091 RunCommand("SYSTEM PROPERTIES", {"getprop"});
2092 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002093
2094 printf("========================================================\n");
2095 printf("== Android Framework Services\n");
2096 printf("========================================================\n");
2097
Vishnu Nair652cc802017-11-30 15:18:30 -08002098 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2099 SEC_TO_MSEC(10));
Hunter Knepshield31cbae12021-05-11 16:23:24 -07002100 RunDumpsys("DUMPSYS", {"vcn_management"}, CommandOptions::WithTimeout(90).Build(),
2101 SEC_TO_MSEC(10));
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08002102 if (include_sensitive_info) {
2103 // Carrier apps' services will be dumped below in dumpsys activity service all-non-platform.
2104 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
2105 SEC_TO_MSEC(10));
2106 } else {
2107 // If the caller is a carrier app and has a carrier service, dump it here since we aren't
2108 // running dumpsys activity service all-non-platform below. Due to the increased output, we
2109 // give a higher timeout as well.
2110 RunDumpsys("DUMPSYS", {"carrier_config", "--requesting-package", calling_package},
2111 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(30));
2112 }
2113 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002114 RunDumpsys("DUMPSYS", {"netpolicy"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2115 RunDumpsys("DUMPSYS", {"network_management"}, CommandOptions::WithTimeout(90).Build(),
Sooraj Sasindrane8d98912018-04-20 11:31:55 -07002116 SEC_TO_MSEC(10));
Hunter Knepshield0fe51b12020-03-05 16:58:20 -08002117 RunDumpsys("DUMPSYS", {"telephony.registry"}, CommandOptions::WithTimeout(90).Build(),
2118 SEC_TO_MSEC(10));
Jack Yu773cc032023-03-16 22:43:39 -07002119 RunDumpsys("DUMPSYS", {"isub"}, CommandOptions::WithTimeout(90).Build(),
2120 SEC_TO_MSEC(10));
Grant Menke56698972023-02-24 13:11:07 -08002121 RunDumpsys("DUMPSYS", {"telecom"}, CommandOptions::WithTimeout(90).Build(),
2122 SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002123 if (include_sensitive_info) {
2124 // Contains raw IP addresses, omit from reports on user builds.
2125 RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2126 // Contains raw destination IP/MAC addresses, omit from reports on user builds.
2127 RunDumpsys("DUMPSYS", {"connmetrics"}, CommandOptions::WithTimeout(90).Build(),
2128 SEC_TO_MSEC(10));
2129 // Contains package/component names, omit from reports on user builds.
2130 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
2131 SEC_TO_MSEC(10));
2132 // Contains package names, but should be relatively simple to remove them (also contains
2133 // UIDs already), omit from reports on user builds.
2134 RunDumpsys("BATTERYSTATS", {"deviceidle"}, CommandOptions::WithTimeout(90).Build(),
2135 SEC_TO_MSEC(10));
2136 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002137
2138 printf("========================================================\n");
2139 printf("== Running Application Services\n");
2140 printf("========================================================\n");
2141
2142 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
2143
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002144 if (include_sensitive_info) {
2145 printf("========================================================\n");
2146 printf("== Running Application Services (non-platform)\n");
2147 printf("========================================================\n");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002148
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002149 // Contains package/component names and potential PII, omit from reports on user builds.
2150 // To get dumps of the active CarrierService(s) on user builds, we supply an argument to the
2151 // carrier_config dumpsys instead.
2152 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
2153 DUMPSYS_COMPONENTS_OPTIONS);
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002154
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002155 printf("========================================================\n");
2156 printf("== Checkins\n");
2157 printf("========================================================\n");
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002158
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002159 // Contains package/component names, omit from reports on user builds.
2160 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
2161 }
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002162
2163 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07002164 printf("== dumpstate: done (id %d)\n", ds.id_);
2165 printf("========================================================\n");
Rhed Jaob5685b32020-08-14 17:19:17 +08002166
2167 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002168 WaitForTask(std::move(dump_board));
Rhed Jaob5685b32020-08-14 17:19:17 +08002169 } else {
2170 RUN_SLOW_FUNCTION_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
2171 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002172}
2173
mukesh agrawal253dad42018-01-23 21:59:59 -08002174// This method collects dumpsys for wifi debugging only
2175static void DumpstateWifiOnly() {
2176 DurationReporter duration_reporter("DUMPSTATE");
2177
Rhed Jaob5685b32020-08-14 17:19:17 +08002178 DumpstateRadioAsRoot();
2179 if (!DropRootUser()) {
2180 return;
2181 }
2182
2183 // Starts thread pool after the root user is dropped. Only one additional
2184 // thread is needed for DumpHals in the DumpstateRadioCommon.
2185 if (ds.dump_pool_) {
2186 ds.dump_pool_->start(/*thread_counts =*/1);
2187 }
2188
mukesh agrawal253dad42018-01-23 21:59:59 -08002189 DumpstateRadioCommon();
2190
2191 printf("========================================================\n");
2192 printf("== Android Framework Services\n");
2193 printf("========================================================\n");
2194
2195 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2196 SEC_TO_MSEC(10));
2197 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
2198 SEC_TO_MSEC(10));
2199
2200 printf("========================================================\n");
2201 printf("== dumpstate: done (id %d)\n", ds.id_);
2202 printf("========================================================\n");
2203}
2204
Elis Elliott8e401ad2023-08-08 11:18:59 +00002205// Collects a lightweight dumpstate to be used for debugging onboarding related flows.
2206static void DumpstateOnboardingOnly() {
2207 ds.AddDir(LOGPERSIST_DATA_DIR, false);
2208}
2209
Christopher Ferris83e0e842024-05-31 13:13:34 -07002210static std::string GetTimestamp(const timespec& ts) {
2211 tm tm;
2212 localtime_r(&ts.tv_sec, &tm);
2213
2214 // Reserve enough space for the entire time string, includes the space
2215 // for the '\0' to make the calculations below easier by using size for
2216 // the total string size.
2217 std::string str(sizeof("1970-01-01 00:00:00.123456789+0830"), '\0');
2218 size_t n = strftime(str.data(), str.size(), "%F %H:%M", &tm);
2219 if (n == 0) {
2220 return "TIMESTAMP FAILURE";
2221 }
2222 int num_chars = snprintf(&str[n], str.size() - n, ":%02d.%09ld", tm.tm_sec, ts.tv_nsec);
2223 if (num_chars > str.size() - n) {
2224 return "TIMESTAMP FAILURE";
2225 }
2226 n += static_cast<size_t>(num_chars);
2227 if (strftime(&str[n], str.size() - n, "%z", &tm) == 0) {
2228 return "TIMESTAMP FAILURE";
2229 }
2230 return str;
2231}
2232
2233static std::string GetCmdline(pid_t pid) {
2234 std::string cmdline;
2235 if (!android::base::ReadFileToString(android::base::StringPrintf("/proc/%d/cmdline", pid),
2236 &cmdline)) {
2237 return "UNKNOWN";
2238 }
2239 // There are '\0' terminators between arguments, convert them to spaces.
2240 // But start by skipping all trailing '\0' values.
2241 size_t cur = cmdline.size() - 1;
2242 while (cur != 0 && cmdline[cur] == '\0') {
2243 cur--;
2244 }
2245 if (cur == 0) {
2246 return "UNKNOWN";
2247 }
2248 while ((cur = cmdline.rfind('\0', cur)) != std::string::npos) {
2249 cmdline[cur] = ' ';
2250 }
2251 return cmdline;
2252}
2253
2254static void DumpPidHeader(int fd, pid_t pid, const timespec& ts) {
2255 // For consistency, the header to this message matches the one
2256 // dumped by debuggerd.
2257 dprintf(fd, "\n----- pid %d at %s -----\n", pid, GetTimestamp(ts).c_str());
2258 dprintf(fd, "Cmd line: %s\n", GetCmdline(pid).c_str());
2259}
2260
2261static void DumpPidFooter(int fd, pid_t pid) {
2262 // For consistency, the footer to this message matches the one
2263 // dumped by debuggerd.
2264 dprintf(fd, "----- end %d -----\n", pid);
2265}
2266
2267static bool DumpBacktrace(int fd, pid_t pid, bool is_java_process) {
2268 int ret = dump_backtrace_to_file_timeout(
2269 pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace, 3, fd);
2270 if (ret == -1 && is_java_process) {
2271 // Tried to unwind as a java process, try a native unwind.
2272 dprintf(fd, "Java unwind failed for pid %d, trying a native unwind.\n", pid);
2273 ret = dump_backtrace_to_file_timeout(pid, kDebuggerdNativeBacktrace, 3, fd);
2274 }
2275 return ret != -1;
2276}
2277
Nandana Duttcf419a72019-03-14 10:40:17 +00002278Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
Gavin Corkery789d7a52021-02-24 23:52:35 +00002279 const std::string temp_file_pattern = ds.bugreport_internal_dir_ + "/dumptrace_XXXXXX";
Nandana Duttfaafd522019-03-11 09:23:09 +00002280 const size_t buf_size = temp_file_pattern.length() + 1;
2281 std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
2282 memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
2283
2284 // Create a new, empty file to receive all trace dumps.
2285 //
2286 // TODO: This can be simplified once we remove support for the old style
2287 // dumps. We can have a file descriptor passed in to dump_traces instead
2288 // of creating a file, closing it and then reopening it again.
2289 android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
2290 if (fd < 0) {
2291 MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002292 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002293 }
2294
2295 // Nobody should have access to this temporary file except dumpstate, but we
2296 // temporarily grant 'read' to 'others' here because this file is created
2297 // when tombstoned is still running as root, but dumped after dropping. This
2298 // can go away once support for old style dumping has.
2299 const int chmod_ret = fchmod(fd, 0666);
2300 if (chmod_ret < 0) {
2301 MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002302 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002303 }
2304
2305 std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
2306 if (proc.get() == nullptr) {
2307 MYLOGE("opendir /proc failed: %s\n", strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002308 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002309 }
2310
2311 // Number of times process dumping has timed out. If we encounter too many
2312 // failures, we'll give up.
2313 int timeout_failures = 0;
2314 bool dalvik_found = false;
2315
Jayant Chowdharya0a8eb22022-05-20 03:30:09 +00002316 const std::set<int> hal_pids = get_interesting_pids();
Nandana Duttfaafd522019-03-11 09:23:09 +00002317
2318 struct dirent* d;
2319 while ((d = readdir(proc.get()))) {
Nandana Duttcf419a72019-03-14 10:40:17 +00002320 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttfaafd522019-03-11 09:23:09 +00002321 int pid = atoi(d->d_name);
2322 if (pid <= 0) {
2323 continue;
2324 }
2325
2326 const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
2327 std::string exe;
2328 if (!android::base::Readlink(link_name, &exe)) {
2329 continue;
2330 }
2331
2332 bool is_java_process;
2333 if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
2334 // Don't bother dumping backtraces for the zygote.
2335 if (IsZygote(pid)) {
2336 continue;
2337 }
2338
2339 dalvik_found = true;
2340 is_java_process = true;
2341 } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
2342 is_java_process = false;
2343 } else {
2344 // Probably a native process we don't care about, continue.
2345 continue;
2346 }
2347
2348 // If 3 backtrace dumps fail in a row, consider debuggerd dead.
2349 if (timeout_failures == 3) {
2350 dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
2351 break;
2352 }
2353
Christopher Ferris83e0e842024-05-31 13:13:34 -07002354 timespec start_timespec;
2355 clock_gettime(CLOCK_REALTIME, &start_timespec);
2356 if (IsCached(pid)) {
2357 DumpPidHeader(fd, pid, start_timespec);
2358 dprintf(fd, "Process is cached, skipping backtrace due to high chance of timeout.\n");
2359 DumpPidFooter(fd, pid);
2360 continue;
2361 }
Nandana Duttfaafd522019-03-11 09:23:09 +00002362
Christopher Ferris83e0e842024-05-31 13:13:34 -07002363 const uint64_t start = Nanotime();
2364 if (!DumpBacktrace(fd, pid, is_java_process)) {
2365 if (IsCached(pid)) {
2366 DumpPidHeader(fd, pid, start_timespec);
2367 dprintf(fd, "Backtrace failed, but process has become cached.\n");
2368 DumpPidFooter(fd, pid);
2369 continue;
2370 }
2371
2372 DumpPidHeader(fd, pid, start_timespec);
2373 dprintf(fd, "Backtrace gathering failed, likely due to a timeout.\n");
2374 DumpPidFooter(fd, pid);
2375
2376 dprintf(fd, "\n[dump %s stack %d: %.3fs elapsed]\n",
2377 is_java_process ? "dalvik" : "native", pid,
2378 (float)(Nanotime() - start) / NANOS_PER_SEC);
Nandana Duttfaafd522019-03-11 09:23:09 +00002379 timeout_failures++;
2380 continue;
2381 }
2382
2383 // We've successfully dumped stack traces, reset the failure count
2384 // and write a summary of the elapsed time to the file and continue with the
2385 // next process.
2386 timeout_failures = 0;
2387
2388 dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
2389 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
2390 }
2391
2392 if (!dalvik_found) {
2393 MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
2394 }
2395
Nandana Duttcf419a72019-03-14 10:40:17 +00002396 *path = file_name_buf.release();
2397 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002398}
2399
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002400static dumpstate_hal_hidl::DumpstateMode GetDumpstateHalModeHidl(
2401 const Dumpstate::BugreportMode bugreport_mode) {
2402 switch (bugreport_mode) {
2403 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2404 return dumpstate_hal_hidl::DumpstateMode::FULL;
2405 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2406 return dumpstate_hal_hidl::DumpstateMode::INTERACTIVE;
2407 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2408 return dumpstate_hal_hidl::DumpstateMode::REMOTE;
2409 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2410 return dumpstate_hal_hidl::DumpstateMode::WEAR;
2411 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2412 return dumpstate_hal_hidl::DumpstateMode::CONNECTIVITY;
2413 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2414 return dumpstate_hal_hidl::DumpstateMode::WIFI;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002415 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002416 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2417 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2418 }
2419 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2420}
2421
2422static dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode GetDumpstateHalModeAidl(
2423 const Dumpstate::BugreportMode bugreport_mode) {
2424 switch (bugreport_mode) {
2425 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2426 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::FULL;
2427 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2428 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::INTERACTIVE;
2429 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2430 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::REMOTE;
2431 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2432 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WEAR;
2433 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2434 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::CONNECTIVITY;
2435 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2436 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WIFI;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002437 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002438 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2439 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2440 }
2441 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2442}
2443
2444static void DoDumpstateBoardHidl(
2445 const sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_1_0,
2446 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2447 const Dumpstate::BugreportMode bugreport_mode,
2448 const size_t timeout_sec) {
2449
2450 using ScopedNativeHandle =
2451 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
2452 ScopedNativeHandle handle(native_handle_create(static_cast<int>(dumpstate_fds.size()), 0),
2453 [](native_handle_t* handle) {
2454 // we don't close file handle's here
2455 // via native_handle_close(handle)
2456 // instead we let dumpstate_fds close the file handles when
2457 // dumpstate_fds gets destroyed
2458 native_handle_delete(handle);
2459 });
2460 if (handle == nullptr) {
2461 MYLOGE("Could not create native_handle for dumpstate HAL\n");
2462 return;
2463 }
2464
2465 for (size_t i = 0; i < dumpstate_fds.size(); i++) {
2466 handle.get()->data[i] = dumpstate_fds[i].get();
2467 }
2468
2469 // Prefer version 1.1 if available. New devices launching with R are no longer allowed to
2470 // implement just 1.0.
2471 const char* descriptor_to_kill;
2472 using DumpstateBoardTask = std::packaged_task<bool()>;
2473 DumpstateBoardTask dumpstate_board_task;
2474 sp<dumpstate_hal_hidl::IDumpstateDevice> dumpstate_hal(
2475 dumpstate_hal_hidl::IDumpstateDevice::castFrom(dumpstate_hal_1_0));
2476 if (dumpstate_hal != nullptr) {
2477 MYLOGI("Using IDumpstateDevice v1.1 HIDL HAL");
2478
2479 dumpstate_hal_hidl::DumpstateMode dumpstate_hal_mode =
2480 GetDumpstateHalModeHidl(bugreport_mode);
2481
2482 descriptor_to_kill = dumpstate_hal_hidl::IDumpstateDevice::descriptor;
2483 dumpstate_board_task =
2484 DumpstateBoardTask([timeout_sec, dumpstate_hal_mode, dumpstate_hal, &handle]() -> bool {
2485 ::android::hardware::Return<dumpstate_hal_hidl::DumpstateStatus> status =
2486 dumpstate_hal->dumpstateBoard_1_1(handle.get(), dumpstate_hal_mode,
2487 SEC_TO_MSEC(timeout_sec));
2488 if (!status.isOk()) {
2489 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2490 return false;
2491 } else if (status != dumpstate_hal_hidl::DumpstateStatus::OK) {
2492 MYLOGE("dumpstateBoard failed with DumpstateStatus::%s\n",
2493 dumpstate_hal_hidl::toString(status).c_str());
2494 return false;
2495 }
2496 return true;
2497 });
2498 } else {
2499 MYLOGI("Using IDumpstateDevice v1.0 HIDL HAL");
2500
2501 descriptor_to_kill = dumpstate_hal_hidl_1_0::IDumpstateDevice::descriptor;
2502 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal_1_0, &handle]() -> bool {
2503 ::android::hardware::Return<void> status =
2504 dumpstate_hal_1_0->dumpstateBoard(handle.get());
2505 if (!status.isOk()) {
2506 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2507 return false;
2508 }
2509 return true;
2510 });
2511 }
2512 auto result = dumpstate_board_task.get_future();
2513 std::thread(std::move(dumpstate_board_task)).detach();
2514
2515 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2516 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2517 if (!android::base::SetProperty(
2518 "ctl.interface_restart",
2519 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2520 MYLOGE("Couldn't restart dumpstate HAL\n");
2521 }
2522 }
2523 // Wait some time for init to kill dumpstate vendor HAL
2524 constexpr size_t killing_timeout_sec = 10;
2525 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2526 MYLOGE(
2527 "killing dumpstateBoard timed out after %zus, continue and "
2528 "there might be racing in content\n",
2529 killing_timeout_sec);
2530 }
2531}
2532
2533static void DoDumpstateBoardAidl(
2534 const std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal,
2535 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2536 const Dumpstate::BugreportMode bugreport_mode, const size_t timeout_sec) {
2537 MYLOGI("Using IDumpstateDevice AIDL HAL");
2538
2539 const char* descriptor_to_kill;
2540 using DumpstateBoardTask = std::packaged_task<bool()>;
2541 DumpstateBoardTask dumpstate_board_task;
2542 dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode dumpstate_hal_mode =
2543 GetDumpstateHalModeAidl(bugreport_mode);
2544
2545 descriptor_to_kill = dumpstate_hal_aidl::IDumpstateDevice::descriptor;
2546 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal, &dumpstate_fds, dumpstate_hal_mode,
2547 timeout_sec]() -> bool {
2548 auto status = dumpstate_hal->dumpstateBoard(dumpstate_fds, dumpstate_hal_mode, timeout_sec);
2549
2550 if (!status.isOk()) {
2551 MYLOGE("dumpstateBoard failed: %s\n", status.getDescription().c_str());
2552 return false;
2553 }
2554 return true;
2555 });
2556 auto result = dumpstate_board_task.get_future();
2557 std::thread(std::move(dumpstate_board_task)).detach();
2558
2559 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2560 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2561 if (!android::base::SetProperty(
2562 "ctl.interface_restart",
2563 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2564 MYLOGE("Couldn't restart dumpstate HAL\n");
2565 }
2566 }
2567 // Wait some time for init to kill dumpstate vendor HAL
2568 constexpr size_t killing_timeout_sec = 10;
2569 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2570 MYLOGE(
2571 "killing dumpstateBoard timed out after %zus, continue and "
2572 "there might be racing in content\n",
2573 killing_timeout_sec);
2574 }
2575}
2576
2577static std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> GetDumpstateBoardAidlService() {
2578 const std::string aidl_instance_name =
2579 std::string(dumpstate_hal_aidl::IDumpstateDevice::descriptor) + "/default";
2580
2581 if (!AServiceManager_isDeclared(aidl_instance_name.c_str())) {
2582 return nullptr;
2583 }
2584
2585 ndk::SpAIBinder dumpstateBinder(AServiceManager_waitForService(aidl_instance_name.c_str()));
2586
2587 return dumpstate_hal_aidl::IDumpstateDevice::fromBinder(dumpstateBinder);
2588}
2589
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002590void Dumpstate::DumpstateBoard(int out_fd) {
2591 dprintf(out_fd, "========================================================\n");
2592 dprintf(out_fd, "== Board\n");
2593 dprintf(out_fd, "========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08002594
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002595 /*
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002596 * mount debugfs for non-user builds with ro.product.debugfs_restrictions.enabled
Hridya Valsaraju51101602021-04-02 14:32:46 -07002597 * set to true and unmount it after invoking dumpstateBoard_* methods.
2598 * This is to enable debug builds to not have debugfs mounted during runtime.
2599 * It will also ensure that debugfs is only accessed by the dumpstate HAL.
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002600 */
Hridya Valsaraju51101602021-04-02 14:32:46 -07002601 auto mount_debugfs =
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002602 android::base::GetBoolProperty("ro.product.debugfs_restrictions.enabled", false);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002603 if (mount_debugfs) {
2604 RunCommand("mount debugfs", {"mount", "-t", "debugfs", "debugfs", "/sys/kernel/debug"},
2605 AS_ROOT_20);
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002606 RunCommand("chmod debugfs", {"chmod", "0755", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002607 }
2608
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002609 std::vector<std::string> paths;
2610 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07002611 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002612 paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
2613 kDumpstateBoardFiles[i].c_str()));
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002614 remover.emplace_back(android::base::make_scope_guard(
2615 std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002616 }
Jie Song9fbfad02017-06-20 16:29:42 -07002617
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002618 // get dumpstate HAL AIDL implementation
2619 std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal_handle_aidl(
2620 GetDumpstateBoardAidlService());
2621 if (dumpstate_hal_handle_aidl == nullptr) {
2622 MYLOGI("No IDumpstateDevice AIDL implementation\n");
2623 }
2624
2625 // get dumpstate HAL HIDL implementation, only if AIDL HAL implementation not found
2626 sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_handle_hidl_1_0 = nullptr;
2627 if (dumpstate_hal_handle_aidl == nullptr) {
2628 dumpstate_hal_handle_hidl_1_0 = dumpstate_hal_hidl_1_0::IDumpstateDevice::getService();
2629 if (dumpstate_hal_handle_hidl_1_0 == nullptr) {
2630 MYLOGI("No IDumpstateDevice HIDL implementation\n");
2631 }
2632 }
2633
2634 // if neither HIDL nor AIDL implementation found, then return
2635 if (dumpstate_hal_handle_hidl_1_0 == nullptr && dumpstate_hal_handle_aidl == nullptr) {
2636 MYLOGE("Could not find IDumpstateDevice implementation\n");
Wei Wang587eac92018-04-05 12:17:20 -07002637 return;
2638 }
2639
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002640 // this is used to hold the file descriptors and when this variable goes out of scope
2641 // the file descriptors are closed
2642 std::vector<::ndk::ScopedFileDescriptor> dumpstate_fds;
Wei Wang587eac92018-04-05 12:17:20 -07002643
Nandana Dutt5c390032019-03-12 10:52:56 +00002644 // TODO(128270426): Check for consent in between?
Wei Wang587eac92018-04-05 12:17:20 -07002645 for (size_t i = 0; i < paths.size(); i++) {
2646 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
2647
2648 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
2649 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
2650 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
2651 if (fd < 0) {
2652 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
2653 return;
2654 }
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002655
2656 dumpstate_fds.emplace_back(fd.release());
2657 // we call fd.release() here to make sure "fd" does not get closed
2658 // after "fd" goes out of scope after this block.
2659 // "fd" will be closed when "dumpstate_fds" goes out of scope
2660 // i.e. when we exit this function
Wei Wang587eac92018-04-05 12:17:20 -07002661 }
2662
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002663 // Given that bugreport is required to diagnose failures, it's better to set an arbitrary amount
2664 // of timeout for IDumpstateDevice than to block the rest of bugreport. In the timeout case, we
2665 // will kill the HAL and grab whatever it dumped in time.
Michael Eastwood8523ea02022-03-10 16:33:08 -08002666 constexpr size_t timeout_sec = 45;
Wei Wang587eac92018-04-05 12:17:20 -07002667
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002668 if (dumpstate_hal_handle_aidl != nullptr) {
2669 DoDumpstateBoardAidl(dumpstate_hal_handle_aidl, dumpstate_fds, options_->bugreport_mode,
2670 timeout_sec);
2671 } else if (dumpstate_hal_handle_hidl_1_0 != nullptr) {
2672 // run HIDL HAL only if AIDL HAL not found
2673 DoDumpstateBoardHidl(dumpstate_hal_handle_hidl_1_0, dumpstate_fds, options_->bugreport_mode,
2674 timeout_sec);
Wei Wang587eac92018-04-05 12:17:20 -07002675 }
2676
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002677 if (mount_debugfs) {
Hridya Valsaraju51101602021-04-02 14:32:46 -07002678 auto keep_debugfs_mounted =
2679 android::base::GetProperty("persist.dbg.keep_debugfs_mounted", "");
2680 if (keep_debugfs_mounted.empty())
2681 RunCommand("unmount debugfs", {"umount", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002682 }
2683
Wei Wang587eac92018-04-05 12:17:20 -07002684 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
2685 for (size_t i = 0; i < paths.size(); i++) {
2686 struct stat s;
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002687 if (fstat(dumpstate_fds[i].get(), &s) == -1) {
2688 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(), strerror(errno));
Wei Wang587eac92018-04-05 12:17:20 -07002689 file_sizes[i] = -1;
2690 continue;
2691 }
2692 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002693 }
2694
2695 for (size_t i = 0; i < paths.size(); i++) {
2696 if (file_sizes[i] == -1) {
2697 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002698 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002699 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07002700 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002701 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002702 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002703 remover[i].Disable();
2704 EnqueueAddZipEntryAndCleanupIfNeeded(kDumpstateBoardFiles[i], paths[i]);
2705 dprintf(out_fd, "*** See %s entry ***\n", kDumpstateBoardFiles[i].c_str());
Jie Song9fbfad02017-06-20 16:29:42 -07002706 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08002707}
2708
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002709static void ShowUsage() {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002710 fprintf(stderr,
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002711 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o directory] [-p] "
2712 "[-s] [-S] [-q] [-P] [-R] [-L] [-V version]\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002713 " -h: display this help message\n"
2714 " -b: play sound file instead of vibrate, at beginning of job\n"
2715 " -e: play sound file instead of vibrate, at end of job\n"
mhasank2d75c442020-06-11 15:05:25 -07002716 " -o: write to custom directory (only in limited mode)\n"
Abhijeet Kaurbb55a3b2019-06-13 18:07:25 +01002717 " -p: capture screenshot to filename.png\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002718 " -s: write zipped file to control socket (for init)\n"
2719 " -S: write file location to control socket (for init)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002720 " -q: disable vibrate\n"
Abhijeet Kaure370d682019-10-01 16:49:30 +01002721 " -P: send broadcast when started and do progress updates\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002722 " -R: take bugreport in remote mode (shouldn't be used with -P)\n"
Nandana Dutt235864b2019-01-22 12:10:16 +00002723 " -w: start binder service and make it wait for a call to startBugreport\n"
mhasankd451a472020-05-26 18:02:39 -07002724 " -L: output limited information that is safe for submission in feedback reports\n"
Felipe Lemed071c682016-10-20 16:48:00 -07002725 " -v: prints the dumpstate header and exit\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002726}
2727
Wei Liuf87959e2016-08-26 14:51:42 -07002728static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07002729 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07002730}
2731
Felipe Leme1d486fe2016-10-14 18:06:47 -07002732bool Dumpstate::FinishZipFile() {
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002733 // Runs all enqueued adding zip entry and cleanup tasks before finishing the zip file.
2734 if (zip_entry_tasks_) {
2735 zip_entry_tasks_->run(/* do_cancel = */false);
2736 }
2737
Felipe Leme9a523ae2016-10-20 15:10:33 -07002738 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07002739 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07002740 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002741 // Final timestamp
2742 char date[80];
2743 time_t the_real_now_please_stand_up = time(nullptr);
2744 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002745 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002746 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002747
Felipe Leme9a523ae2016-10-20 15:10:33 -07002748 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002749 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08002750 return false;
2751 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07002752 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002753 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08002754 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08002755 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08002756
Felipe Leme0f3fb202016-06-10 17:10:53 -07002757 // Add log file (which contains stderr output) to zip...
2758 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002759 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07002760 MYLOGE("Failed to add dumpstate log to .zip file\n");
2761 return false;
2762 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002763 // TODO: Should truncate the existing file.
2764 // ... and re-open it for further logging.
Nandana Dutta344cb62019-02-22 15:12:35 +00002765 if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
2766 return false;
2767 }
Felipe Leme0f3fb202016-06-10 17:10:53 -07002768 fprintf(stderr, "\n");
2769
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002770 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07002771 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002772 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002773 return false;
2774 }
2775
Felipe Leme1d486fe2016-10-14 18:06:47 -07002776 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
2777 ds.zip_file.reset(nullptr);
2778
Felipe Lemee9d2c542016-11-15 11:48:26 -08002779 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002780 android::os::UnlinkAndLogOnError(tmp_path_);
Felipe Lemec4eee562016-04-21 15:42:55 -07002781
Felipe Leme1e9edc62015-12-21 16:02:13 -08002782 return true;
2783}
Felipe Leme6e01fa62015-11-11 19:35:14 -08002784
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00002785static void SendBroadcast(const std::string& action,
2786 const std::vector<std::string>& args,
2787 int32_t user_id) {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002788 // clang-format off
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00002789 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user",
2790 std::to_string(user_id), "--receiver-foreground",
2791 "--receiver-include-background", "-a", action};
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002792 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08002793
2794 am.insert(am.end(), args.begin(), args.end());
2795
Felipe Leme8d2410e2017-02-08 09:46:08 -08002796 RunCommand("", am,
2797 CommandOptions::WithTimeout(20)
2798 .Log("Sending broadcast: '%s'\n")
2799 .Always()
2800 .DropRoot()
2801 .RedirectStderr()
2802 .Build());
2803}
2804
Felipe Leme35b8cf12017-02-10 15:47:29 -08002805static void Vibrate(int duration_ms) {
2806 // clang-format off
Lais Andrade51156962021-02-22 19:21:35 +00002807 std::vector<std::string> args = {"cmd", "vibrator_manager", "synced", "-f", "-d", "dumpstate",
2808 "oneshot", std::to_string(duration_ms)};
2809 RunCommand("", args,
Felipe Leme35b8cf12017-02-10 15:47:29 -08002810 CommandOptions::WithTimeout(10)
2811 .Log("Vibrate: '%s'\n")
2812 .Always()
2813 .Build());
2814 // clang-format on
2815}
2816
Nandana Dutt979388e2018-11-30 16:48:55 +00002817static void MaybeResolveSymlink(std::string* path) {
2818 std::string resolved_path;
2819 if (android::base::Readlink(*path, &resolved_path)) {
2820 *path = resolved_path;
2821 }
2822}
2823
Nandana Dutt4be45d12018-09-26 15:04:23 +01002824/*
2825 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002826 * and adds the version file. Return false if zip_file could not be open to write.
Nandana Dutt4be45d12018-09-26 15:04:23 +01002827 */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002828static bool PrepareToWriteToFile() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002829 MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2830
Nandana Dutt4be45d12018-09-26 15:04:23 +01002831 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2832 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002833 ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002834 char date[80];
2835 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2836 ds.name_ = date;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002837
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002838 if (ds.options_->telephony_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002839 ds.base_name_ += "-telephony";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002840 } else if (ds.options_->wifi_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002841 ds.base_name_ += "-wifi";
2842 }
2843
Paul Chang0d2aad72020-02-13 20:04:03 +08002844 if (ds.options_->do_screenshot) {
Nandana Dutt9d17b942020-03-26 10:02:59 +00002845 ds.screenshot_path_ = ds.GetPath(ds.CalledByApi() ? "-png.tmp" : ".png");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002846 }
2847 ds.tmp_path_ = ds.GetPath(".tmp");
2848 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2849
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01002850 std::string destination = ds.CalledByApi()
Nandana Dutt54dbd672019-01-11 12:58:05 +00002851 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
Nandana Dutt9a76d202019-01-21 15:56:48 +00002852 : ds.bugreport_internal_dir_.c_str();
Nandana Dutt4be45d12018-09-26 15:04:23 +01002853 MYLOGD(
Nandana Dutt235c6672019-11-14 15:22:32 +00002854 "Bugreport dir: [%s] "
2855 "Base name: [%s] "
2856 "Suffix: [%s] "
2857 "Log path: [%s] "
2858 "Temporary path: [%s] "
2859 "Screenshot path: [%s]\n",
Nandana Dutt9a76d202019-01-21 15:56:48 +00002860 destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2861 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002862
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002863 ds.path_ = ds.GetPath(ds.CalledByApi() ? "-zip.tmp" : ".zip");
2864 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2865 create_parent_dirs(ds.path_.c_str());
2866 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2867 if (ds.zip_file == nullptr) {
2868 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2869 return false;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002870 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002871 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2872 ds.AddTextZipEntry("version.txt", ds.version_);
2873 return true;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002874}
2875
2876/*
Abhijeet Kaure370d682019-10-01 16:49:30 +01002877 * Finalizes writing to the file by zipping the tmp file to the final location,
Nandana Dutt4be45d12018-09-26 15:04:23 +01002878 * printing zipped file status, etc.
2879 */
2880static void FinalizeFile() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002881 bool do_text_file = !ds.FinishZipFile();
2882 if (do_text_file) {
2883 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002884 }
mhasank2d75c442020-06-11 15:05:25 -07002885
2886 std::string final_path = ds.path_;
2887 if (ds.options_->OutputToCustomFile()) {
mhasank3a4cfb42020-06-15 18:06:43 -07002888 final_path = ds.GetPath(ds.options_->out_dir, ".zip");
mhasank2d75c442020-06-11 15:05:25 -07002889 android::os::CopyFileToFile(ds.path_, final_path);
2890 }
2891
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002892 if (ds.options_->stream_to_socket) {
2893 android::os::CopyFileToFd(ds.path_, ds.control_socket_fd_);
2894 } else if (ds.options_->progress_updates_to_socket) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002895 if (do_text_file) {
2896 dprintf(ds.control_socket_fd_,
2897 "FAIL:could not create zip file, check %s "
2898 "for more details\n",
2899 ds.log_path_.c_str());
2900 } else {
mhasank2d75c442020-06-11 15:05:25 -07002901 dprintf(ds.control_socket_fd_, "OK:%s\n", final_path.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002902 }
2903 }
2904}
2905
Nandana Dutt4be45d12018-09-26 15:04:23 +01002906
Nandana Dutt58d72e22018-11-16 10:30:48 +00002907static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2908 switch (mode) {
2909 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2910 return "BUGREPORT_FULL";
2911 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2912 return "BUGREPORT_INTERACTIVE";
2913 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2914 return "BUGREPORT_REMOTE";
2915 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2916 return "BUGREPORT_WEAR";
2917 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2918 return "BUGREPORT_TELEPHONY";
2919 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2920 return "BUGREPORT_WIFI";
Elis Elliott8e401ad2023-08-08 11:18:59 +00002921 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
2922 return "BUGREPORT_ONBOARDING";
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002923 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2924 return "BUGREPORT_DEFAULT";
Nandana Dutt58d72e22018-11-16 10:30:48 +00002925 }
2926}
2927
Steven Leeb573eb82022-11-29 22:31:35 +08002928static bool IsConsentlessBugreportAllowed(const Dumpstate::DumpOptions& options) {
2929 // only BUGREPORT_TELEPHONY does not allow using consentless bugreport
2930 return !options.telephony_only;
2931}
2932
Paul Changf59c2b72020-03-10 02:08:55 +08002933static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options,
2934 bool is_screenshot_requested) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002935 // Modify com.android.shell.BugreportProgressService#isDefaultScreenshotRequired as well for
2936 // default system screenshots.
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002937 options->bugreport_mode = mode;
2938 options->bugreport_mode_string = ModeToString(mode);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002939 switch (mode) {
2940 case Dumpstate::BugreportMode::BUGREPORT_FULL:
Paul Changf59c2b72020-03-10 02:08:55 +08002941 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002942 break;
2943 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002944 // Currently, the dumpstate binder is only used by Shell to update progress.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002945 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002946 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002947 break;
2948 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002949 options->do_vibrate = false;
2950 options->is_remote_mode = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002951 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002952 break;
2953 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
Robert Ginda55ecebd2023-04-03 22:53:13 +00002954 options->do_vibrate = false;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002955 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002956 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002957 break;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002958 // TODO(b/148168577) rename TELEPHONY everywhere to CONNECTIVITY.
Nandana Dutt58d72e22018-11-16 10:30:48 +00002959 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002960 options->telephony_only = true;
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002961 options->do_progress_updates = 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_WIFI:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002965 options->wifi_only = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002966 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002967 break;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002968 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
2969 options->onboarding_only = true;
2970 options->do_screenshot = false;
2971 break;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002972 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2973 break;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002974 }
2975}
2976
Nandana Dutt58d72e22018-11-16 10:30:48 +00002977static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
Nandana Dutt235c6672019-11-14 15:22:32 +00002978 MYLOGI(
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002979 "do_vibrate: %d stream_to_socket: %d progress_updates_to_socket: %d do_screenshot: %d "
Rhed Jao25f50e02020-08-20 00:10:32 +08002980 "is_remote_mode: %d show_header_only: %d telephony_only: %d "
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002981 "wifi_only: %d do_progress_updates: %d fd: %d bugreport_mode: %s "
mhasankd451a472020-05-26 18:02:39 -07002982 "limited_only: %d args: %s\n",
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002983 options.do_vibrate, options.stream_to_socket, options.progress_updates_to_socket,
Paul Chang0d2aad72020-02-13 20:04:03 +08002984 options.do_screenshot, options.is_remote_mode, options.show_header_only,
Rhed Jao25f50e02020-08-20 00:10:32 +08002985 options.telephony_only, options.wifi_only,
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002986 options.do_progress_updates, options.bugreport_fd.get(),
2987 options.bugreport_mode_string.c_str(),
2988 options.limited_only, options.args.c_str());
Nandana Dutt58d72e22018-11-16 10:30:48 +00002989}
2990
Nandana Dutt54dbd672019-01-11 12:58:05 +00002991void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
Kean Mariotti306633e2022-09-05 16:30:47 +00002992 int bugreport_flags,
Nandana Dutt54dbd672019-01-11 12:58:05 +00002993 const android::base::unique_fd& bugreport_fd_in,
Paul Changf59c2b72020-03-10 02:08:55 +08002994 const android::base::unique_fd& screenshot_fd_in,
Kholoud Mohameddef4e432024-05-15 12:47:46 +00002995 bool is_screenshot_requested,
2996 bool skip_user_consent) {
Kean Mariotti306633e2022-09-05 16:30:47 +00002997 this->use_predumped_ui_data = bugreport_flags & BugreportFlag::BUGREPORT_USE_PREDUMPED_UI_DATA;
Gavin Corkerya44686c2022-11-23 18:16:51 +00002998 this->is_consent_deferred = bugreport_flags & BugreportFlag::BUGREPORT_FLAG_DEFER_CONSENT;
Kholoud Mohameddef4e432024-05-15 12:47:46 +00002999 this->skip_user_consent = skip_user_consent;
Nandana Dutt54dbd672019-01-11 12:58:05 +00003000 // Duplicate the fds because the passed in fds don't outlive the binder transaction.
Todd Frederick621533f2022-03-26 02:54:17 +00003001 bugreport_fd.reset(fcntl(bugreport_fd_in.get(), F_DUPFD_CLOEXEC, 0));
3002 screenshot_fd.reset(fcntl(screenshot_fd_in.get(), F_DUPFD_CLOEXEC, 0));
Nandana Dutt58d72e22018-11-16 10:30:48 +00003003
Paul Changf59c2b72020-03-10 02:08:55 +08003004 SetOptionsFromMode(bugreport_mode, this, is_screenshot_requested);
Nandana Dutt58d72e22018-11-16 10:30:48 +00003005}
3006
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003007Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
3008 RunStatus status = RunStatus::OK;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003009 int c;
mhasankd451a472020-05-26 18:02:39 -07003010 while ((c = getopt(argc, argv, "dho:svqzpLPBRSV:w")) != -1) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003011 switch (c) {
3012 // clang-format off
mhasank3a4cfb42020-06-15 18:06:43 -07003013 case 'o': out_dir = optarg; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003014 case 's': stream_to_socket = true; break;
3015 case 'S': progress_updates_to_socket = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003016 case 'v': show_header_only = true; break;
3017 case 'q': do_vibrate = false; break;
Paul Chang0d2aad72020-02-13 20:04:03 +08003018 case 'p': do_screenshot = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003019 case 'P': do_progress_updates = true; break;
3020 case 'R': is_remote_mode = true; break;
mhasankd451a472020-05-26 18:02:39 -07003021 case 'L': limited_only = true; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003022 case 'V':
3023 case 'd':
3024 case 'z':
3025 // compatibility no-op
3026 break;
Nandana Dutt235864b2019-01-22 12:10:16 +00003027 case 'w':
3028 // This was already processed
3029 break;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003030 case 'h':
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003031 status = RunStatus::HELP;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003032 break;
3033 default:
3034 fprintf(stderr, "Invalid option: %c\n", c);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003035 status = RunStatus::INVALID_INPUT;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003036 break;
3037 // clang-format on
3038 }
3039 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08003040
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003041 for (int i = 0; i < argc; i++) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003042 args += argv[i];
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003043 if (i < argc - 1) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003044 args += " ";
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003045 }
3046 }
3047
3048 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
3049 optind = 1;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003050
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003051 return status;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003052}
3053
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003054bool Dumpstate::DumpOptions::ValidateOptions() const {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003055 if (bugreport_fd.get() != -1 && stream_to_socket) {
Nandana Dutt979388e2018-11-30 16:48:55 +00003056 return false;
3057 }
3058
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003059 if ((progress_updates_to_socket || do_progress_updates) && stream_to_socket) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003060 return false;
3061 }
3062
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003063 if (is_remote_mode && (do_progress_updates || stream_to_socket)) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003064 return false;
3065 }
3066 return true;
3067}
3068
Nandana Dutt197661d2018-11-16 16:40:21 +00003069void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
3070 options_ = std::move(options);
3071}
3072
Abhijeet Kaura407fb82020-03-27 12:51:12 +00003073void Dumpstate::Initialize() {
3074 /* gets the sequential id */
3075 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
3076 id_ = ++last_id;
3077 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
3078}
3079
Nandana Duttd2f5f082019-01-18 17:13:52 +00003080Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
3081 Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
Gavin Corkerya44686c2022-11-23 18:16:51 +00003082 HandleRunStatus(status);
3083 return status;
3084}
3085
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003086Dumpstate::RunStatus Dumpstate::Retrieve(int32_t calling_uid, const std::string& calling_package,
Kholoud Mohameddef4e432024-05-15 12:47:46 +00003087 const bool keep_bugreport_on_retrieval,
3088 const bool skip_user_consent) {
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003089 Dumpstate::RunStatus status = RetrieveInternal(calling_uid, calling_package,
Kholoud Mohameddef4e432024-05-15 12:47:46 +00003090 keep_bugreport_on_retrieval,
3091 skip_user_consent);
Gavin Corkerya44686c2022-11-23 18:16:51 +00003092 HandleRunStatus(status);
3093 return status;
3094}
3095
3096Dumpstate::RunStatus Dumpstate::RetrieveInternal(int32_t calling_uid,
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003097 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) {
3100 if (!android::app::admin::flags::onboarding_consentless_bugreports() || !skip_user_consent) {
3101 consent_callback_ = new ConsentCallback();
3102 const String16 incidentcompanion("incidentcompanion");
3103 sp<android::IBinder> ics(
3104 defaultServiceManager()->checkService(incidentcompanion));
3105 android::String16 package(calling_package.c_str());
3106 if (ics != nullptr) {
3107 MYLOGD("Checking user consent via incidentcompanion service\n");
3108
3109 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
3110 calling_uid, package, String16(), String16(),
3111 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
3112 } else {
3113 MYLOGD(
3114 "Unable to check user consent; incidentcompanion service unavailable\n");
3115 return RunStatus::USER_CONSENT_TIMED_OUT;
3116 }
3117 UserConsentResult consent_result = consent_callback_->getResult();
3118 int timeout_ms = 30 * 1000;
3119 while (consent_result == UserConsentResult::UNAVAILABLE &&
3120 consent_callback_->getElapsedTimeMs() < timeout_ms) {
3121 sleep(1);
3122 consent_result = consent_callback_->getResult();
3123 }
3124 if (consent_result == UserConsentResult::DENIED) {
3125 return RunStatus::USER_CONSENT_DENIED;
3126 }
3127 if (consent_result == UserConsentResult::UNAVAILABLE) {
3128 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3129 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3130 consent_callback_.get());
3131 return RunStatus::USER_CONSENT_TIMED_OUT;
3132 }
Gavin Corkerya44686c2022-11-23 18:16:51 +00003133 }
3134
3135 bool copy_succeeded =
3136 android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003137
3138 if (copy_succeeded && (!android::app::admin::flags::onboarding_bugreport_v2_enabled()
3139 || !keep_bugreport_on_retrieval)) {
3140 android::os::UnlinkAndLogOnError(path_);
Gavin Corkerya44686c2022-11-23 18:16:51 +00003141 }
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003142
Gavin Corkerya44686c2022-11-23 18:16:51 +00003143 return copy_succeeded ? Dumpstate::RunStatus::OK
3144 : Dumpstate::RunStatus::ERROR;
3145}
3146
3147void Dumpstate::HandleRunStatus(Dumpstate::RunStatus status) {
3148 if (listener_ != nullptr) {
Nandana Duttbabf6c72019-01-15 14:11:12 +00003149 switch (status) {
3150 case Dumpstate::RunStatus::OK:
Gavin Corkerya44686c2022-11-23 18:16:51 +00003151 listener_->onFinished(path_.c_str());
Nandana Duttbabf6c72019-01-15 14:11:12 +00003152 break;
3153 case Dumpstate::RunStatus::HELP:
3154 break;
3155 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003156 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00003157 break;
3158 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003159 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
3160 break;
3161 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3162 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
3163 break;
3164 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
3165 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00003166 break;
3167 }
3168 }
Nandana Duttbabf6c72019-01-15 14:11:12 +00003169}
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003170void Dumpstate::Cancel() {
3171 CleanupTmpFiles();
3172 android::os::UnlinkAndLogOnError(log_path_);
3173 for (int i = 0; i < NUM_OF_DUMPS; i++) {
3174 android::os::UnlinkAndLogOnError(ds.bugreport_internal_dir_ + "/" +
3175 kDumpstateBoardFiles[i]);
3176 }
3177 tombstone_data_.clear();
3178 anr_data_.clear();
Andy Hungd62f7e62024-01-11 15:47:52 -08003179 anr_trace_data_.clear();
Woody Lin20767a92022-11-29 15:50:24 +08003180 shutdown_checkpoints_.clear();
Rhed Jao0daac912020-08-21 14:48:20 +08003181
3182 // Instead of shutdown the pool, we delete temporary files directly since
3183 // shutdown blocking the call.
3184 if (dump_pool_) {
3185 dump_pool_->deleteTempFiles();
3186 }
3187 if (zip_entry_tasks_) {
3188 zip_entry_tasks_->run(/*do_cancel =*/ true);
3189 }
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003190}
3191
Kean Mariotti306633e2022-09-05 16:30:47 +00003192void Dumpstate::PreDumpUiData() {
Kean Mariottica20f2d2023-12-15 09:34:25 +00003193 auto snapshot_system_trace = MaybeSnapshotSystemTraceAsync();
Kean Mariotti306633e2022-09-05 16:30:47 +00003194 MaybeSnapshotUiTraces();
Kean Mariottica20f2d2023-12-15 09:34:25 +00003195 MaybeWaitForSnapshotSystemTrace(std::move(snapshot_system_trace));
Kean Mariotti306633e2022-09-05 16:30:47 +00003196}
3197
Nandana Dutt979388e2018-11-30 16:48:55 +00003198/*
3199 * Dumps relevant information to a bugreport based on the given options.
3200 *
3201 * The bugreport can be dumped to a file or streamed to a socket.
3202 *
3203 * How dumping to file works:
3204 * stdout is redirected to a temporary file. This will later become the main bugreport entry.
3205 * stderr is redirected a log file.
3206 *
3207 * The temporary bugreport is then populated via printfs, dumping contents of files and
3208 * output of commands to stdout.
3209 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003210 * A bunch of other files and dumps are added to the zip archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00003211 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003212 * The temporary bugreport file and the log file also get added to the archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00003213 *
mhasank2d75c442020-06-11 15:05:25 -07003214 * Bugreports are first generated in a local directory and later copied to the caller's fd
3215 * or directory if supplied.
Nandana Dutt979388e2018-11-30 16:48:55 +00003216 */
Nandana Duttd2f5f082019-01-18 17:13:52 +00003217Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
3218 const std::string& calling_package) {
Rhed Jao5377d792020-07-16 17:37:39 +08003219 DurationReporter duration_reporter("RUN INTERNAL", /* logcat_only = */true);
Nandana Dutt979388e2018-11-30 16:48:55 +00003220 LogDumpOptions(*options_);
Nandana Dutt197661d2018-11-16 16:40:21 +00003221 if (!options_->ValidateOptions()) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00003222 MYLOGE("Invalid options specified\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003223 return RunStatus::INVALID_INPUT;
3224 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003225 /* set as high priority, and protect from OOM killer */
3226 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003227
Felipe Lemed071c682016-10-20 16:48:00 -07003228 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07003229 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003230 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003231 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003232 } else {
3233 /* fallback to kernels <= 2.6.35 */
3234 oom_adj = fopen("/proc/self/oom_adj", "we");
3235 if (oom_adj) {
3236 fputs("-17", oom_adj);
3237 fclose(oom_adj);
3238 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003239 }
3240
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003241 if (version_ == VERSION_DEFAULT) {
3242 version_ = VERSION_CURRENT;
Michal Karpinski4db754f2015-12-11 18:04:32 +00003243 }
3244
Chris Morin5a50d482022-02-01 17:41:18 -08003245 if (version_ != VERSION_CURRENT) {
3246 MYLOGE("invalid version requested ('%s'); supported values are: ('%s', '%s')\n",
3247 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003248 return RunStatus::INVALID_INPUT;
Felipe Lemed071c682016-10-20 16:48:00 -07003249 }
3250
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003251 if (options_->show_header_only) {
3252 PrintHeader();
3253 return RunStatus::OK;
Felipe Lemed071c682016-10-20 16:48:00 -07003254 }
3255
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003256 MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n",
3257 calling_uid, calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003258
Felipe Leme7447d7c2016-11-03 18:12:22 -07003259 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003260 std::string stats_path =
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003261 android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003262 progress_.reset(new Progress(stats_path));
Felipe Leme7447d7c2016-11-03 18:12:22 -07003263
Sahana Raof35ed432019-07-12 10:47:52 +01003264 if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
3265 MYLOGE("Failed to acquire wake lock: %s\n", strerror(errno));
3266 } else {
3267 // Wake lock will be released automatically on process death
3268 MYLOGD("Wake lock acquired.\n");
3269 }
3270
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08003271 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07003272
Felipe Lemef0292972016-11-22 13:57:05 -08003273 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07003274 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
3275 }
3276
Kevin Jeonfa64e642023-07-27 11:36:41 -04003277 if (PropertiesHelper::IsStrictRun()) {
3278 MYLOGI(
3279 "Running on strict-run mode, which has shorter timeouts "
3280 "(to disable, call 'setprop dumpstate.strict_run false')\n");
3281 }
3282
Nandana Dutt235c6672019-11-14 15:22:32 +00003283 MYLOGI("dumpstate info: id=%d, args='%s', bugreport_mode= %s bugreport format version: %s\n",
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00003284 id_, options_->args.c_str(), options_->bugreport_mode_string.c_str(), version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08003285
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003286 do_early_screenshot_ = options_->do_progress_updates;
Felipe Lemee338bf62015-12-07 14:03:50 -08003287
Christopher Ferrised9354f2014-10-01 17:35:01 -07003288 // If we are going to use a socket, do it as early as possible
3289 // to avoid timeouts from bugreport.
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003290 if (options_->stream_to_socket || options_->progress_updates_to_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07003291 MYLOGD("Opening control socket\n");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003292 control_socket_fd_ = open_socket_fn_("dumpstate");
Nandana Dutta344cb62019-02-22 15:12:35 +00003293 if (control_socket_fd_ == -1) {
3294 return ERROR;
3295 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003296 if (options_->progress_updates_to_socket) {
3297 options_->do_progress_updates = 1;
3298 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07003299 }
3300
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003301 if (!PrepareToWriteToFile()) {
3302 return ERROR;
3303 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08003304
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003305 // Interactive, wear & telephony modes are default to true.
3306 // and may enable from cli option or when using control socket
3307 if (options_->do_progress_updates) {
3308 // clang-format off
3309 std::vector<std::string> am_args = {
3310 "--receiver-permission", "android.permission.DUMP",
3311 };
3312 // clang-format on
3313 // Send STARTED broadcast for apps that listen to bugreport generation events
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003314 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED",
3315 am_args, multiuser_get_user_id(calling_uid));
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003316 if (options_->progress_updates_to_socket) {
3317 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08003318 }
3319 }
3320
Nick Kralevichf3599b32016-01-25 15:05:16 -08003321 /* read /proc/cmdline before dropping root */
3322 FILE *cmdline = fopen("/proc/cmdline", "re");
3323 if (cmdline) {
3324 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
3325 fclose(cmdline);
3326 }
3327
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003328 if (options_->do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08003329 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05003330 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003331
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003332 if (zip_file != nullptr) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003333 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
3334 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003335 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08003336 }
3337 }
3338
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003339 int dup_stdout_fd;
3340 int dup_stderr_fd;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003341 // Redirect stderr to log_path_ for debugging.
3342 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
3343 if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
3344 return ERROR;
3345 }
3346 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
3347 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
3348 strerror(errno));
3349 }
Nandana Dutt979388e2018-11-30 16:48:55 +00003350
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003351 // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
3352 // moved into zip file later, if zipping.
3353 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
3354 // TODO: why not write to a file instead of stdout to overcome this problem?
3355 /* TODO: rather than generating a text file now and zipping it later,
3356 it would be more efficient to redirect stdout to the zip entry
3357 directly, but the libziparchive doesn't support that option yet. */
3358 if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
3359 return ERROR;
3360 }
3361 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
3362 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
3363 tmp_path_.c_str(), strerror(errno));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003364 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08003365
3366 // Don't buffer stdout
3367 setvbuf(stdout, nullptr, _IONBF, 0);
3368
Rhed Jao5377d792020-07-16 17:37:39 +08003369 // Enable the parallel run if the client requests to output to a file.
3370 EnableParallelRunIfNeeded();
3371 // Using scope guard to make sure the dump pool can be shut down correctly.
3372 auto scope_guard_to_shutdown_pool = android::base::make_scope_guard([=]() {
3373 ShutdownDumpPool();
3374 });
3375
Felipe Leme608385d2016-02-01 10:35:38 -08003376 // NOTE: there should be no stdout output until now, otherwise it would break the header.
3377 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08003378 // duration is logged into MYLOG instead.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003379 PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003380
Kean Mariottic14cebc2024-03-04 10:55:28 +00003381 bool system_trace_exists = access(SYSTEM_TRACE_SNAPSHOT, F_OK) == 0;
3382 if (options_->use_predumped_ui_data && !system_trace_exists) {
3383 MYLOGW("Ignoring 'use predumped data' flag because no predumped data is available");
3384 options_->use_predumped_ui_data = false;
3385 }
3386
Kean Mariottica20f2d2023-12-15 09:34:25 +00003387 std::future<std::string> snapshot_system_trace;
3388
Kean Mariotti853b73a2023-07-27 12:40:30 +00003389 bool is_dumpstate_restricted =
3390 options_->telephony_only || options_->wifi_only || options_->limited_only;
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003391 if (!is_dumpstate_restricted) {
3392 // Snapshot the system trace now (if running) to avoid that dumpstate's
3393 // own activity pushes out interesting data from the trace ring buffer.
3394 // The trace file is added to the zip by MaybeAddSystemTraceToZip().
Kean Mariottica20f2d2023-12-15 09:34:25 +00003395 snapshot_system_trace = MaybeSnapshotSystemTraceAsync();
Yohei Yukawa95305b32021-03-09 07:54:27 -08003396
Kean Mariotti853b73a2023-07-27 12:40:30 +00003397 // Invoke critical dumpsys to preserve system state, before doing anything else.
3398 RunDumpsysCritical();
3399
Kean Mariotti306633e2022-09-05 16:30:47 +00003400 // Snapshot the UI traces now (if running).
3401 // The trace files will be added to bugreport later.
3402 MaybeSnapshotUiTraces();
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003403 }
Kean Mariotti853b73a2023-07-27 12:40:30 +00003404
3405 MaybeTakeEarlyScreenshot();
Kean Mariottica20f2d2023-12-15 09:34:25 +00003406 MaybeWaitForSnapshotSystemTrace(std::move(snapshot_system_trace));
Gavin Corkery6968f552020-11-22 18:09:05 +00003407 onUiIntensiveBugreportDumpsFinished(calling_uid);
3408 MaybeCheckUserConsent(calling_uid, calling_package);
3409 if (options_->telephony_only) {
3410 DumpstateTelephonyOnly(calling_package);
3411 } else if (options_->wifi_only) {
3412 DumpstateWifiOnly();
3413 } else if (options_->limited_only) {
3414 DumpstateLimitedOnly();
Elis Elliott8e401ad2023-08-08 11:18:59 +00003415 } else if (options_->onboarding_only) {
3416 DumpstateOnboardingOnly();
Gavin Corkery6968f552020-11-22 18:09:05 +00003417 } else {
Nandana Dutt4be45d12018-09-26 15:04:23 +01003418 // Dump state for the default case. This also drops root.
Jichao Lie89d9c12019-11-21 19:02:51 -08003419 RunStatus s = DumpstateDefaultAfterCritical();
Nandana Dutt5c390032019-03-12 10:52:56 +00003420 if (s != RunStatus::OK) {
Nandana Duttaac6f582019-07-26 14:32:47 +01003421 if (s == RunStatus::USER_CONSENT_DENIED) {
Nandana Dutt5c390032019-03-12 10:52:56 +00003422 HandleUserConsentDenied();
3423 }
3424 return s;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08003425 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07003426 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07003427
Felipe Leme55b42a62015-11-10 17:39:08 -08003428 /* close output if needed */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003429 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003430
Abhijeet Kaure370d682019-10-01 16:49:30 +01003431 // Zip the (now complete) .tmp file within the internal directory.
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003432 ATRACE_BEGIN("FinalizeFile");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003433 FinalizeFile();
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003434 ATRACE_END();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003435
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003436 // Share the final file with the caller if the user has consented or Shell is the caller.
Nandana Duttd2f5f082019-01-18 17:13:52 +00003437 Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
Gavin Corkerya44686c2022-11-23 18:16:51 +00003438 if (CalledByApi() && !options_->is_consent_deferred) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003439 status = CopyBugreportIfUserConsented(calling_uid);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003440 if (status != Dumpstate::RunStatus::OK &&
3441 status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3442 // Do an early return if there were errors. We make an exception for consent
3443 // timing out because it's possible the user got distracted. In this case the
3444 // bugreport is not shared but made available for manual retrieval.
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003445 MYLOGI("User denied consent. Returning\n");
Nandana Duttd2f5f082019-01-18 17:13:52 +00003446 return status;
3447 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003448 if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3449 MYLOGI(
3450 "Did not receive user consent yet."
3451 " Will not copy the bugreport artifacts to caller.\n");
Abhijeet Kaur57627412019-04-17 16:00:09 +01003452 const String16 incidentcompanion("incidentcompanion");
3453 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
3454 if (ics != nullptr) {
3455 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3456 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3457 consent_callback_.get());
3458 } else {
3459 MYLOGD("Unable to cancel user consent; incidentcompanion service unavailable\n");
3460 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003461 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003462 }
3463
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003464 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003465 if (options_->do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09003466 for (int i = 0; i < 3; i++) {
3467 Vibrate(75);
3468 usleep((75 + 50) * 1000);
3469 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003470 }
3471
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003472 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
3473 progress_->GetInitialMax());
3474 progress_->Save();
3475 MYLOGI("done (id %d)\n", id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003476
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003477 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08003478
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003479 if (control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07003480 MYLOGD("Closing control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003481 close(control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07003482 }
3483
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003484 tombstone_data_.clear();
3485 anr_data_.clear();
Andy Hungd62f7e62024-01-11 15:47:52 -08003486 anr_trace_data_.clear();
Woody Lin20767a92022-11-29 15:50:24 +08003487 shutdown_checkpoints_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01003488
Nandana Duttd2f5f082019-01-18 17:13:52 +00003489 return (consent_callback_ != nullptr &&
3490 consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
3491 ? USER_CONSENT_TIMED_OUT
3492 : RunStatus::OK;
3493}
3494
Paul Chang0d2aad72020-02-13 20:04:03 +08003495void Dumpstate::MaybeTakeEarlyScreenshot() {
3496 if (!options_->do_screenshot || !do_early_screenshot_) {
3497 return;
3498 }
3499
3500 TakeScreenshot();
3501}
3502
Kean Mariottica20f2d2023-12-15 09:34:25 +00003503std::future<std::string> Dumpstate::MaybeSnapshotSystemTraceAsync() {
Kean Mariotti853b73a2023-07-27 12:40:30 +00003504 // When capturing traces via bugreport handler (BH), this function will be invoked twice:
3505 // 1) When BH invokes IDumpstate::PreDumpUiData()
3506 // 2) When BH invokes IDumpstate::startBugreport(flags = BUGREPORT_USE_PREDUMPED_UI_DATA)
3507 // In this case we don't want to re-invoke perfetto in step 2.
3508 // In all other standard invocation states, this function is invoked once
3509 // without the flag BUGREPORT_USE_PREDUMPED_UI_DATA.
Kean Mariottica20f2d2023-12-15 09:34:25 +00003510 // This function must run asynchronously to avoid delaying MaybeTakeEarlyScreenshot() in the
3511 // standard invocation states (b/316110955).
Kean Mariotti853b73a2023-07-27 12:40:30 +00003512 if (options_->use_predumped_ui_data) {
Kean Mariottica20f2d2023-12-15 09:34:25 +00003513 return {};
3514 }
3515
3516 // Create temporary file for the command's output
3517 std::string outPath = ds.bugreport_internal_dir_ + "/tmp_serialize_perfetto_trace";
3518 auto outFd = android::base::unique_fd(TEMP_FAILURE_RETRY(
3519 open(outPath.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
3520 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
3521 if (outFd < 0) {
3522 MYLOGE("Could not open %s to serialize perfetto trace.\n", outPath.c_str());
3523 return {};
Kean Mariotti853b73a2023-07-27 12:40:30 +00003524 }
3525
3526 // If a stale file exists already, remove it.
3527 unlink(SYSTEM_TRACE_SNAPSHOT);
3528
Kean Mariottica20f2d2023-12-15 09:34:25 +00003529 MYLOGI("Launching async '%s'", SERIALIZE_PERFETTO_TRACE_TASK.c_str())
3530 return std::async(
3531 std::launch::async, [this, outPath = std::move(outPath), outFd = std::move(outFd)] {
3532 // If a background system trace is happening and is marked as "suitable for
3533 // bugreport" (i.e. bugreport_score > 0 in the trace config), this command
3534 // will stop it and serialize into SYSTEM_TRACE_SNAPSHOT. In the (likely)
3535 // case that no trace is ongoing, this command is a no-op.
3536 // Note: this should not be enqueued as we need to freeze the trace before
3537 // dumpstate starts. Otherwise the trace ring buffers will contain mostly
3538 // the dumpstate's own activity which is irrelevant.
3539 RunCommand(
3540 SERIALIZE_PERFETTO_TRACE_TASK, {"perfetto", "--save-for-bugreport"},
Kean Mariotti5aa8d152024-09-23 12:10:09 +00003541 CommandOptions::WithTimeout(30).DropRoot().CloseAllFileDescriptorsOnExec().Build(),
Kean Mariottica20f2d2023-12-15 09:34:25 +00003542 false, outFd);
3543 // MaybeAddSystemTraceToZip() will take care of copying the trace in the zip
3544 // file in the later stages.
3545
3546 return outPath;
3547 });
3548}
3549
3550void Dumpstate::MaybeWaitForSnapshotSystemTrace(std::future<std::string> task) {
3551 if (!task.valid()) {
3552 return;
3553 }
3554
3555 WaitForTask(std::move(task), SERIALIZE_PERFETTO_TRACE_TASK, STDOUT_FILENO);
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003556}
3557
Kean Mariotti306633e2022-09-05 16:30:47 +00003558void Dumpstate::MaybeSnapshotUiTraces() {
3559 if (PropertiesHelper::IsUserBuild() || options_->use_predumped_ui_data) {
3560 return;
3561 }
3562
Pablo Gamito654831c2024-02-16 16:47:48 +00003563 std::vector<std::vector<std::string>> dumpTracesForBugReportCommands = {
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003564 {"cmd", "input_method", "tracing", "save-for-bugreport"},
3565 {"cmd", "window", "tracing", "save-for-bugreport"},
3566 {"cmd", "window", "shell", "tracing", "save-for-bugreport"},
3567 };
Hongwei Wang39229132023-01-24 15:09:59 -08003568
Pablo Gamito654831c2024-02-16 16:47:48 +00003569 if (!android_tracing_perfetto_transition_tracing()) {
3570 dumpTracesForBugReportCommands.push_back({"dumpsys", "activity", "service",
3571 "SystemUIService", "WMShell", "transitions",
3572 "tracing", "save-for-bugreport"});
3573 }
3574
Pablo Gamito6929a0e2024-02-26 23:29:47 +00003575 if (!android_tracing_perfetto_protolog_tracing()) {
Pablo Gamito654831c2024-02-16 16:47:48 +00003576 dumpTracesForBugReportCommands.push_back({"dumpsys", "activity", "service",
3577 "SystemUIService", "WMShell", "protolog",
3578 "save-for-bugreport"});
3579 }
3580
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003581 for (const auto& command : dumpTracesForBugReportCommands) {
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003582 RunCommand(
3583 // Empty name because it's not intended to be classified as a bugreport section.
3584 // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003585 "", command,
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003586 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
3587 }
Kean Mariotti306633e2022-09-05 16:30:47 +00003588}
3589
3590void Dumpstate::MaybeAddUiTracesToZip() {
3591 if (PropertiesHelper::IsUserBuild()) {
3592 return;
3593 }
3594
3595 ds.AddDir(WMTRACE_DATA_DIR, false);
Yohei Yukawa95305b32021-03-09 07:54:27 -08003596}
3597
Paul Changeb4b4642020-05-28 22:05:47 +08003598void Dumpstate::onUiIntensiveBugreportDumpsFinished(int32_t calling_uid) {
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003599 if (multiuser_get_app_id(calling_uid) == AID_SHELL || !CalledByApi()) {
Paul Changc490e662020-04-11 18:14:09 +08003600 return;
3601 }
3602 if (listener_ != nullptr) {
3603 // Let listener know ui intensive bugreport dumps are finished, then it can do event
3604 // handling if required.
Paul Changeb4b4642020-05-28 22:05:47 +08003605 listener_->onUiIntensiveBugreportDumpsFinished();
Paul Changc490e662020-04-11 18:14:09 +08003606 }
3607}
3608
Jichao Lie89d9c12019-11-21 19:02:51 -08003609void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) {
Gavin Corkerya44686c2022-11-23 18:16:51 +00003610 if (multiuser_get_app_id(calling_uid) == AID_SHELL ||
Kholoud Mohameddef4e432024-05-15 12:47:46 +00003611 !CalledByApi() || options_->is_consent_deferred ||
3612 (android::app::admin::flags::onboarding_consentless_bugreports() &&
3613 options_->skip_user_consent)) {
Gavin Corkerya44686c2022-11-23 18:16:51 +00003614 // No need to get consent for shell triggered dumpstates, or not
3615 // through bugreporting API (i.e. no fd to copy back), or when consent
3616 // is deferred.
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003617 return;
3618 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003619 consent_callback_ = new ConsentCallback();
3620 const String16 incidentcompanion("incidentcompanion");
3621 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
Jichao Lie89d9c12019-11-21 19:02:51 -08003622 android::String16 package(calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003623 if (ics != nullptr) {
3624 MYLOGD("Checking user consent via incidentcompanion service\n");
Steven Leeb573eb82022-11-29 22:31:35 +08003625 int flags = 0x1; // IncidentManager.FLAG_CONFIRMATION_DIALOG
3626 if (IsConsentlessBugreportAllowed(*options_)) {
3627 flags |= 0x2; // IncidentManager.FLAG_ALLOW_CONSENTLESS_BUGREPORT
3628 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003629 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
Steven Leeb573eb82022-11-29 22:31:35 +08003630 calling_uid, package, String16(), String16(), flags, consent_callback_.get());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003631 } else {
3632 MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
3633 }
3634}
3635
Nandana Dutt5c390032019-03-12 10:52:56 +00003636bool Dumpstate::IsUserConsentDenied() const {
3637 return ds.consent_callback_ != nullptr &&
3638 ds.consent_callback_->getResult() == UserConsentResult::DENIED;
3639}
3640
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01003641bool Dumpstate::CalledByApi() const {
3642 return ds.options_->bugreport_fd.get() != -1 ? true : false;
3643}
3644
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003645void Dumpstate::CleanupTmpFiles() {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003646 android::os::UnlinkAndLogOnError(tmp_path_);
3647 android::os::UnlinkAndLogOnError(screenshot_path_);
3648 android::os::UnlinkAndLogOnError(path_);
Gavin Corkery789d7a52021-02-24 23:52:35 +00003649 if (dump_traces_path != nullptr) {
3650 android::os::UnlinkAndLogOnError(dump_traces_path);
3651 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003652}
3653
Rhed Jao5377d792020-07-16 17:37:39 +08003654void Dumpstate::EnableParallelRunIfNeeded() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003655 if (!PropertiesHelper::IsParallelRun()) {
Rhed Jao5377d792020-07-16 17:37:39 +08003656 return;
3657 }
3658 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003659 zip_entry_tasks_ = std::make_unique<TaskQueue>();
Rhed Jao5377d792020-07-16 17:37:39 +08003660}
3661
3662void Dumpstate::ShutdownDumpPool() {
3663 if (dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08003664 dump_pool_.reset();
Rhed Jao5377d792020-07-16 17:37:39 +08003665 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003666 if (zip_entry_tasks_) {
3667 zip_entry_tasks_->run(/* do_cancel = */true);
3668 zip_entry_tasks_ = nullptr;
3669 }
3670}
3671
3672void Dumpstate::EnqueueAddZipEntryAndCleanupIfNeeded(const std::string& entry_name,
3673 const std::string& entry_path) {
3674 auto func_add_zip_entry_and_cleanup = [=](bool task_cancelled) {
3675 if (!task_cancelled) {
3676 AddZipEntry(entry_name, entry_path);
3677 }
3678 android::os::UnlinkAndLogOnError(entry_path);
3679 };
3680 if (zip_entry_tasks_) {
3681 // Enqueues AddZipEntryAndCleanup function if the parallel run is enabled.
3682 zip_entry_tasks_->add(func_add_zip_entry_and_cleanup, _1);
3683 } else {
3684 // Invokes AddZipEntryAndCleanup immediately
3685 std::invoke(func_add_zip_entry_and_cleanup, /* task_cancelled = */false);
3686 }
Rhed Jao5377d792020-07-16 17:37:39 +08003687}
3688
Nandana Duttd2f5f082019-01-18 17:13:52 +00003689Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
3690 MYLOGD("User denied consent; deleting files and returning\n");
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003691 CleanupTmpFiles();
Nandana Duttd2f5f082019-01-18 17:13:52 +00003692 return USER_CONSENT_DENIED;
3693}
3694
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003695Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented(int32_t calling_uid) {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003696 // If the caller has asked to copy the bugreport over to their directory, we need explicit
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003697 // user consent (unless the caller is Shell).
3698 UserConsentResult consent_result;
Kholoud Mohameddef4e432024-05-15 12:47:46 +00003699 if (multiuser_get_app_id(calling_uid) == AID_SHELL || (options_->skip_user_consent
3700 && android::app::admin::flags::onboarding_consentless_bugreports())) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003701 consent_result = UserConsentResult::APPROVED;
3702 } else {
3703 consent_result = consent_callback_->getResult();
3704 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003705 if (consent_result == UserConsentResult::UNAVAILABLE) {
3706 // User has not responded yet.
3707 uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
Hunter Knepshield70610fa2020-01-03 15:27:33 -08003708 // Telephony is a fast report type, particularly on user builds where information may be
3709 // more aggressively limited. To give the user time to read the consent dialog, increase the
3710 // timeout.
3711 uint64_t timeout_ms = options_->telephony_only ? TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS
3712 : USER_CONSENT_TIMEOUT_MS;
3713 if (elapsed_ms < timeout_ms) {
3714 uint delay_seconds = (timeout_ms - elapsed_ms) / 1000;
Nandana Duttd2f5f082019-01-18 17:13:52 +00003715 MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
3716 sleep(delay_seconds);
3717 }
3718 consent_result = consent_callback_->getResult();
3719 }
3720 if (consent_result == UserConsentResult::DENIED) {
3721 // User has explicitly denied sharing with the app. To be safe delete the
3722 // internal bugreport & tmp files.
3723 return HandleUserConsentDenied();
3724 }
3725 if (consent_result == UserConsentResult::APPROVED) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00003726 bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
3727 if (copy_succeeded) {
3728 android::os::UnlinkAndLogOnError(path_);
Abhijeet Kaur9ce94672020-04-01 17:22:36 +01003729 if (options_->do_screenshot &&
3730 options_->screenshot_fd.get() != -1 &&
3731 !options_->is_screenshot_copied) {
3732 copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
3733 options_->screenshot_fd.get());
3734 options_->is_screenshot_copied = copy_succeeded;
3735 if (copy_succeeded) {
3736 android::os::UnlinkAndLogOnError(screenshot_path_);
3737 }
3738 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003739 }
3740 return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
3741 } else if (consent_result == UserConsentResult::UNAVAILABLE) {
3742 // consent_result is still UNAVAILABLE. The user has likely not responded yet.
3743 // Since we do not have user consent to share the bugreport it does not get
3744 // copied over to the calling app but remains in the internal directory from
3745 // where the user can manually pull it.
Paul Changce644212021-05-11 16:06:45 +08003746 std::string final_path = GetPath(".zip");
3747 bool copy_succeeded = android::os::CopyFileToFile(path_, final_path);
3748 if (copy_succeeded) {
3749 android::os::UnlinkAndLogOnError(path_);
3750 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003751 return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
3752 }
3753 // Unknown result; must be a programming error.
3754 MYLOGE("Unknown user consent result:%d\n", consent_result);
3755 return Dumpstate::RunStatus::ERROR;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003756}
3757
Nandana Duttf02564e2019-02-15 15:24:24 +00003758Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003759 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
3760 Dumpstate::RunStatus status = options->Initialize(argc, argv);
3761 if (status == Dumpstate::RunStatus::OK) {
Nandana Duttf02564e2019-02-15 15:24:24 +00003762 SetOptions(std::move(options));
Nandana Duttd2f5f082019-01-18 17:13:52 +00003763 // When directly running dumpstate binary, the output is not expected to be written
3764 // to any external file descriptor.
Nandana Duttf02564e2019-02-15 15:24:24 +00003765 assert(options_->bugreport_fd.get() == -1);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003766
3767 // calling_uid and calling_package are for user consent to share the bugreport with
Abhijeet Kaura407fb82020-03-27 12:51:12 +00003768 // an app; they are irrelevant here because bugreport is triggered via command line.
3769 // Update Last ID before calling Run().
3770 Initialize();
Nikhil Kumarb70622a2023-06-15 15:37:19 +01003771 status = Run(0 /* calling_uid */, "" /* calling_package */);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003772 }
Nandana Duttf02564e2019-02-15 15:24:24 +00003773 return status;
3774}
3775
3776/* Main entry point for dumpstate binary. */
3777int run_main(int argc, char* argv[]) {
3778 Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003779
3780 switch (status) {
3781 case Dumpstate::RunStatus::OK:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003782 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003783 case Dumpstate::RunStatus::HELP:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003784 ShowUsage();
3785 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003786 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003787 fprintf(stderr, "Invalid combination of args\n");
3788 ShowUsage();
3789 exit(1);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003790 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003791 FALLTHROUGH_INTENDED;
3792 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3793 FALLTHROUGH_INTENDED;
3794 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003795 exit(2);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003796 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003797}
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003798
3799// TODO(111441001): Default DumpOptions to sensible values.
3800Dumpstate::Dumpstate(const std::string& version)
3801 : pid_(getpid()),
3802 options_(new Dumpstate::DumpOptions()),
Nandana Dutt402a8392019-06-14 14:25:13 +01003803 last_reported_percent_progress_(0),
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003804 version_(version),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003805 now_(time(nullptr)),
3806 open_socket_fn_(open_socket) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003807}
3808
3809Dumpstate& Dumpstate::GetInstance() {
3810 static Dumpstate singleton_(android::base::GetProperty("dumpstate.version", VERSION_CURRENT));
3811 return singleton_;
3812}
3813
Rhed Jao5377d792020-07-16 17:37:39 +08003814DurationReporter::DurationReporter(const std::string& title, bool logcat_only, bool verbose,
3815 int duration_fd) : title_(title), logcat_only_(logcat_only), verbose_(verbose),
3816 duration_fd_(duration_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003817 if (!title_.empty()) {
3818 started_ = Nanotime();
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003819 if (title_.find("SHOW MAP") == std::string::npos) {
3820 ATRACE_ASYNC_BEGIN(title_.c_str(), 0);
3821 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003822 }
3823}
3824
3825DurationReporter::~DurationReporter() {
3826 if (!title_.empty()) {
3827 float elapsed = (float)(Nanotime() - started_) / NANOS_PER_SEC;
chenqiwuaf8b2d92019-12-12 18:53:51 +08003828 if (elapsed >= .5f || verbose_) {
3829 MYLOGD("Duration of '%s': %.2fs\n", title_.c_str(), elapsed);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003830 }
chenqiwuaf8b2d92019-12-12 18:53:51 +08003831 if (!logcat_only_) {
3832 // Use "Yoda grammar" to make it easier to grep|sort sections.
Rhed Jao5377d792020-07-16 17:37:39 +08003833 dprintf(duration_fd_, "------ %.3fs was the duration of '%s' ------\n",
3834 elapsed, title_.c_str());
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003835 }
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003836 if (title_.find("SHOW MAP") == std::string::npos) {
3837 ATRACE_ASYNC_END(title_.c_str(), 0);
3838 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003839 }
3840}
3841
3842const int32_t Progress::kDefaultMax = 5000;
3843
3844Progress::Progress(const std::string& path) : Progress(Progress::kDefaultMax, 1.1, path) {
3845}
3846
3847Progress::Progress(int32_t initial_max, int32_t progress, float growth_factor)
3848 : Progress(initial_max, growth_factor, "") {
3849 progress_ = progress;
3850}
3851
3852Progress::Progress(int32_t initial_max, float growth_factor, const std::string& path)
3853 : initial_max_(initial_max),
3854 progress_(0),
3855 max_(initial_max),
3856 growth_factor_(growth_factor),
3857 n_runs_(0),
3858 average_max_(0),
3859 path_(path) {
3860 if (!path_.empty()) {
3861 Load();
3862 }
3863}
3864
3865void Progress::Load() {
3866 MYLOGD("Loading stats from %s\n", path_.c_str());
3867 std::string content;
3868 if (!android::base::ReadFileToString(path_, &content)) {
3869 MYLOGI("Could not read stats from %s; using max of %d\n", path_.c_str(), max_);
3870 return;
3871 }
3872 if (content.empty()) {
3873 MYLOGE("No stats (empty file) on %s; using max of %d\n", path_.c_str(), max_);
3874 return;
3875 }
3876 std::vector<std::string> lines = android::base::Split(content, "\n");
3877
3878 if (lines.size() < 1) {
3879 MYLOGE("Invalid stats on file %s: not enough lines (%d). Using max of %d\n", path_.c_str(),
3880 (int)lines.size(), max_);
3881 return;
3882 }
3883 char* ptr;
3884 n_runs_ = strtol(lines[0].c_str(), &ptr, 10);
3885 average_max_ = strtol(ptr, nullptr, 10);
3886 if (n_runs_ <= 0 || average_max_ <= 0 || n_runs_ > STATS_MAX_N_RUNS ||
3887 average_max_ > STATS_MAX_AVERAGE) {
3888 MYLOGE("Invalid stats line on file %s: %s\n", path_.c_str(), lines[0].c_str());
3889 initial_max_ = Progress::kDefaultMax;
3890 } else {
3891 initial_max_ = average_max_;
3892 }
3893 max_ = initial_max_;
3894
3895 MYLOGI("Average max progress: %d in %d runs; estimated max: %d\n", average_max_, n_runs_, max_);
3896}
3897
3898void Progress::Save() {
3899 int32_t total = n_runs_ * average_max_ + progress_;
3900 int32_t runs = n_runs_ + 1;
3901 int32_t average = floor(((float)total) / runs);
3902 MYLOGI("Saving stats (total=%d, runs=%d, average=%d) on %s\n", total, runs, average,
3903 path_.c_str());
3904 if (path_.empty()) {
3905 return;
3906 }
3907
3908 std::string content = android::base::StringPrintf("%d %d\n", runs, average);
3909 if (!android::base::WriteStringToFile(content, path_)) {
3910 MYLOGE("Could not save stats on %s\n", path_.c_str());
3911 }
3912}
3913
3914int32_t Progress::Get() const {
3915 return progress_;
3916}
3917
3918bool Progress::Inc(int32_t delta_sec) {
3919 bool changed = false;
3920 if (delta_sec >= 0) {
3921 progress_ += delta_sec;
3922 if (progress_ > max_) {
3923 int32_t old_max = max_;
3924 max_ = floor((float)progress_ * growth_factor_);
3925 MYLOGD("Adjusting max progress from %d to %d\n", old_max, max_);
3926 changed = true;
3927 }
3928 }
3929 return changed;
3930}
3931
3932int32_t Progress::GetMax() const {
3933 return max_;
3934}
3935
3936int32_t Progress::GetInitialMax() const {
3937 return initial_max_;
3938}
3939
3940void Progress::Dump(int fd, const std::string& prefix) const {
3941 const char* pr = prefix.c_str();
3942 dprintf(fd, "%sprogress: %d\n", pr, progress_);
3943 dprintf(fd, "%smax: %d\n", pr, max_);
3944 dprintf(fd, "%sinitial_max: %d\n", pr, initial_max_);
3945 dprintf(fd, "%sgrowth_factor: %0.2f\n", pr, growth_factor_);
3946 dprintf(fd, "%spath: %s\n", pr, path_.c_str());
3947 dprintf(fd, "%sn_runs: %d\n", pr, n_runs_);
3948 dprintf(fd, "%saverage_max: %d\n", pr, average_max_);
3949}
3950
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003951std::string Dumpstate::GetPath(const std::string& suffix) const {
3952 return GetPath(bugreport_internal_dir_, suffix);
3953}
3954
3955std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
3956 return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
3957 name_.c_str(), suffix.c_str());
3958}
3959
3960void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
3961 progress_ = std::move(progress);
3962}
3963
3964void for_each_userid(void (*func)(int), const char *header) {
3965 std::string title = header == nullptr ? "for_each_userid" : android::base::StringPrintf(
3966 "for_each_userid(%s)", header);
3967 DurationReporter duration_reporter(title);
3968 if (PropertiesHelper::IsDryRun()) return;
3969
3970 DIR *d;
3971 struct dirent *de;
3972
3973 if (header) printf("\n------ %s ------\n", header);
3974 func(0);
3975
3976 if (!(d = opendir("/data/system/users"))) {
3977 printf("Failed to open /data/system/users (%s)\n", strerror(errno));
3978 return;
3979 }
3980
3981 while ((de = readdir(d))) {
3982 int userid;
3983 if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
3984 continue;
3985 }
3986 func(userid);
3987 }
3988
3989 closedir(d);
3990}
3991
3992static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
3993 DIR *d;
3994 struct dirent *de;
3995
3996 if (!(d = opendir("/proc"))) {
3997 printf("Failed to open /proc (%s)\n", strerror(errno));
3998 return;
3999 }
4000
4001 if (header) printf("\n------ %s ------\n", header);
4002 while ((de = readdir(d))) {
4003 if (ds.IsUserConsentDenied()) {
4004 MYLOGE(
4005 "Returning early because user denied consent to share bugreport with calling app.");
4006 closedir(d);
4007 return;
4008 }
4009 int pid;
4010 int fd;
4011 char cmdpath[255];
4012 char cmdline[255];
4013
4014 if (!(pid = atoi(de->d_name))) {
4015 continue;
4016 }
4017
4018 memset(cmdline, 0, sizeof(cmdline));
4019
4020 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
4021 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
4022 TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
4023 close(fd);
4024 if (cmdline[0]) {
4025 helper(pid, cmdline, arg);
4026 continue;
4027 }
4028 }
4029
4030 // if no cmdline, a kernel thread has comm
4031 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
4032 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
4033 TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
4034 close(fd);
4035 if (cmdline[1]) {
4036 cmdline[0] = '[';
4037 size_t len = strcspn(cmdline, "\f\b\r\n");
4038 cmdline[len] = ']';
4039 cmdline[len+1] = '\0';
4040 }
4041 }
4042 if (!cmdline[0]) {
4043 strcpy(cmdline, "N/A");
4044 }
4045 helper(pid, cmdline, arg);
4046 }
4047
4048 closedir(d);
4049}
4050
4051static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
4052 for_each_pid_func *func = (for_each_pid_func*) arg;
4053 func(pid, cmdline);
4054}
4055
4056void for_each_pid(for_each_pid_func func, const char *header) {
4057 std::string title = header == nullptr ? "for_each_pid"
4058 : android::base::StringPrintf("for_each_pid(%s)", header);
4059 DurationReporter duration_reporter(title);
4060 if (PropertiesHelper::IsDryRun()) return;
4061
4062 __for_each_pid(for_each_pid_helper, header, (void *) func);
4063}
4064
4065static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
4066 DIR *d;
4067 struct dirent *de;
4068 char taskpath[255];
4069 for_each_tid_func *func = (for_each_tid_func *) arg;
4070
4071 snprintf(taskpath, sizeof(taskpath), "/proc/%d/task", pid);
4072
4073 if (!(d = opendir(taskpath))) {
4074 printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
4075 return;
4076 }
4077
4078 func(pid, pid, cmdline);
4079
4080 while ((de = readdir(d))) {
4081 if (ds.IsUserConsentDenied()) {
4082 MYLOGE(
4083 "Returning early because user denied consent to share bugreport with calling app.");
4084 closedir(d);
4085 return;
4086 }
4087 int tid;
4088 int fd;
4089 char commpath[255];
4090 char comm[255];
4091
4092 if (!(tid = atoi(de->d_name))) {
4093 continue;
4094 }
4095
4096 if (tid == pid)
4097 continue;
4098
4099 snprintf(commpath, sizeof(commpath), "/proc/%d/comm", tid);
4100 memset(comm, 0, sizeof(comm));
4101 if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
4102 strcpy(comm, "N/A");
4103 } else {
4104 char *c;
4105 TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
4106 close(fd);
4107
4108 c = strrchr(comm, '\n');
4109 if (c) {
4110 *c = '\0';
4111 }
4112 }
4113 func(pid, tid, comm);
4114 }
4115
4116 closedir(d);
4117}
4118
4119void for_each_tid(for_each_tid_func func, const char *header) {
4120 std::string title = header == nullptr ? "for_each_tid"
4121 : android::base::StringPrintf("for_each_tid(%s)", header);
4122 DurationReporter duration_reporter(title);
4123
4124 if (PropertiesHelper::IsDryRun()) return;
4125
4126 __for_each_pid(for_each_tid_helper, header, (void *) func);
4127}
4128
4129void show_wchan(int pid, int tid, const char *name) {
4130 if (PropertiesHelper::IsDryRun()) return;
4131
4132 char path[255];
4133 char buffer[255];
4134 int fd, ret, save_errno;
4135 char name_buffer[255];
4136
4137 memset(buffer, 0, sizeof(buffer));
4138
4139 snprintf(path, sizeof(path), "/proc/%d/wchan", tid);
4140 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
4141 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
4142 return;
4143 }
4144
4145 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
4146 save_errno = errno;
4147 close(fd);
4148
4149 if (ret < 0) {
4150 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
4151 return;
4152 }
4153
4154 snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
4155 pid == tid ? 0 : 3, "", name);
4156
4157 printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
4158
4159 return;
4160}
4161
4162// print time in centiseconds
4163static void snprcent(char *buffer, size_t len, size_t spc,
4164 unsigned long long time) {
4165 static long hz; // cache discovered hz
4166
4167 if (hz <= 0) {
4168 hz = sysconf(_SC_CLK_TCK);
4169 if (hz <= 0) {
4170 hz = 1000;
4171 }
4172 }
4173
4174 // convert to centiseconds
4175 time = (time * 100 + (hz / 2)) / hz;
4176
4177 char str[16];
4178
4179 snprintf(str, sizeof(str), " %llu.%02u",
4180 time / 100, (unsigned)(time % 100));
4181 size_t offset = strlen(buffer);
4182 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
4183 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
4184}
4185
4186// print permille as a percent
4187static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
4188 char str[16];
4189
4190 snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
4191 size_t offset = strlen(buffer);
4192 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
4193 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
4194}
4195
4196void show_showtime(int pid, const char *name) {
4197 if (PropertiesHelper::IsDryRun()) return;
4198
4199 char path[255];
4200 char buffer[1023];
4201 int fd, ret, save_errno;
4202
4203 memset(buffer, 0, sizeof(buffer));
4204
4205 snprintf(path, sizeof(path), "/proc/%d/stat", pid);
4206 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
4207 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
4208 return;
4209 }
4210
4211 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
4212 save_errno = errno;
4213 close(fd);
4214
4215 if (ret < 0) {
4216 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
4217 return;
4218 }
4219
4220 // field 14 is utime
4221 // field 15 is stime
4222 // field 42 is iotime
4223 unsigned long long utime = 0, stime = 0, iotime = 0;
4224 if (sscanf(buffer,
4225 "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
4226 "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
4227 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
4228 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
4229 &utime, &stime, &iotime) != 3) {
4230 return;
4231 }
4232
4233 unsigned long long total = utime + stime;
4234 if (!total) {
4235 return;
4236 }
4237
4238 unsigned permille = (iotime * 1000 + (total / 2)) / total;
4239 if (permille > 1000) {
4240 permille = 1000;
4241 }
4242
4243 // try to beautify and stabilize columns at <80 characters
4244 snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
4245 if ((name[0] != '[') || utime) {
4246 snprcent(buffer, sizeof(buffer), 57, utime);
4247 }
4248 snprcent(buffer, sizeof(buffer), 65, stime);
4249 if ((name[0] != '[') || iotime) {
4250 snprcent(buffer, sizeof(buffer), 73, iotime);
4251 }
4252 if (iotime) {
4253 snprdec(buffer, sizeof(buffer), 79, permille);
4254 }
4255 puts(buffer); // adds a trailing newline
4256
4257 return;
4258}
4259
4260void do_dmesg() {
4261 const char *title = "KERNEL LOG (dmesg)";
4262 DurationReporter duration_reporter(title);
4263 printf("------ %s ------\n", title);
4264
4265 if (PropertiesHelper::IsDryRun()) return;
4266
4267 /* Get size of kernel buffer */
4268 int size = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
4269 if (size <= 0) {
4270 printf("Unexpected klogctl return value: %d\n\n", size);
4271 return;
4272 }
4273 char *buf = (char *) malloc(size + 1);
4274 if (buf == nullptr) {
4275 printf("memory allocation failed\n\n");
4276 return;
4277 }
4278 int retval = klogctl(KLOG_READ_ALL, buf, size);
4279 if (retval < 0) {
4280 printf("klogctl failure\n\n");
4281 free(buf);
4282 return;
4283 }
4284 buf[retval] = '\0';
4285 printf("%s\n\n", buf);
4286 free(buf);
4287 return;
4288}
4289
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004290int Dumpstate::DumpFile(const std::string& title, const std::string& path) {
4291 DurationReporter duration_reporter(title);
4292
4293 int status = DumpFileToFd(STDOUT_FILENO, title, path);
4294
4295 UpdateProgress(WEIGHT_FILE);
4296
4297 return status;
4298}
4299
4300int read_file_as_long(const char *path, long int *output) {
luoqiangwei15fcf2022024-03-07 15:29:20 +08004301 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
4302 if (fd.get() < 0) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004303 int err = errno;
4304 MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
4305 return -1;
4306 }
4307 char buffer[50];
luoqiangwei15fcf2022024-03-07 15:29:20 +08004308 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer, sizeof(buffer)));
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004309 if (bytes_read == -1) {
4310 MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
4311 return -2;
4312 }
4313 if (bytes_read == 0) {
4314 MYLOGE("File %s is empty\n", path);
4315 return -3;
4316 }
4317 *output = atoi(buffer);
4318 return 0;
4319}
4320
4321/* calls skip to gate calling dump_from_fd recursively
4322 * in the specified directory. dump_from_fd defaults to
4323 * dump_file_from_fd above when set to NULL. skip defaults
4324 * to false when set to NULL. dump_from_fd will always be
4325 * called with title NULL.
4326 */
4327int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
4328 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4329 DurationReporter duration_reporter(title);
4330 DIR *dirp;
4331 struct dirent *d;
4332 char *newpath = nullptr;
4333 const char *slash = "/";
4334 int retval = 0;
4335
4336 if (!title.empty()) {
4337 printf("------ %s (%s) ------\n", title.c_str(), dir);
4338 }
4339 if (PropertiesHelper::IsDryRun()) return 0;
4340
4341 if (dir[strlen(dir) - 1] == '/') {
4342 ++slash;
4343 }
4344 dirp = opendir(dir);
4345 if (dirp == nullptr) {
4346 retval = -errno;
4347 MYLOGE("%s: %s\n", dir, strerror(errno));
4348 return retval;
4349 }
4350
4351 if (!dump_from_fd) {
4352 dump_from_fd = dump_file_from_fd;
4353 }
4354 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4355 if ((d->d_name[0] == '.')
4356 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4357 || (d->d_name[1] == '\0'))) {
4358 continue;
4359 }
4360 asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
4361 (d->d_type == DT_DIR) ? "/" : "");
4362 if (!newpath) {
4363 retval = -errno;
4364 continue;
4365 }
4366 if (skip && (*skip)(newpath)) {
4367 continue;
4368 }
4369 if (d->d_type == DT_DIR) {
4370 int ret = dump_files("", newpath, skip, dump_from_fd);
4371 if (ret < 0) {
4372 retval = ret;
4373 }
4374 continue;
4375 }
4376 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
4377 if (fd.get() < 0) {
4378 retval = -1;
4379 printf("*** %s: %s\n", newpath, strerror(errno));
4380 continue;
4381 }
4382 (*dump_from_fd)(nullptr, newpath, fd.get());
4383 }
4384 closedir(dirp);
4385 if (!title.empty()) {
4386 printf("\n");
4387 }
4388 return retval;
4389}
4390
4391/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
4392 * it's possible to avoid issues where opening the file itself can get
4393 * stuck.
4394 */
4395int dump_file_from_fd(const char *title, const char *path, int fd) {
4396 if (PropertiesHelper::IsDryRun()) return 0;
4397
4398 int flags = fcntl(fd, F_GETFL);
4399 if (flags == -1) {
4400 printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
4401 return -1;
4402 } else if (!(flags & O_NONBLOCK)) {
4403 printf("*** %s: fd must have O_NONBLOCK set.\n", path);
4404 return -1;
4405 }
4406 return DumpFileFromFdToFd(title, path, fd, STDOUT_FILENO, PropertiesHelper::IsDryRun());
4407}
4408
4409int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004410 const CommandOptions& options, bool verbose_duration, int out_fd) {
4411 DurationReporter duration_reporter(title, false /* logcat_only */,
4412 verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004413
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004414 int status = RunCommandToFd(out_fd, title, full_command, options);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004415
4416 /* TODO: for now we're simplifying the progress calculation by using the
4417 * timeout as the weight. It's a good approximation for most cases, except when calling dumpsys,
4418 * where its weight should be much higher proportionally to its timeout.
4419 * Ideally, it should use a options.EstimatedDuration() instead...*/
4420 UpdateProgress(options.Timeout());
4421
4422 return status;
4423}
4424
4425void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
Rhed Jaoe017f982020-07-21 17:58:41 +08004426 const CommandOptions& options, long dumpsysTimeoutMs, int out_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004427 long timeout_ms = dumpsysTimeoutMs > 0 ? dumpsysTimeoutMs : options.TimeoutInMs();
4428 std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-T", std::to_string(timeout_ms)};
4429 dumpsys.insert(dumpsys.end(), dumpsys_args.begin(), dumpsys_args.end());
Rhed Jaoe017f982020-07-21 17:58:41 +08004430 RunCommand(title, dumpsys, options, false, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004431}
4432
Dieter Hsu105ad0c2020-09-29 15:23:33 +08004433static int open_socket(const char* service) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004434 int s = android_get_control_socket(service);
4435 if (s < 0) {
4436 MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
4437 return -1;
4438 }
4439 fcntl(s, F_SETFD, FD_CLOEXEC);
4440
4441 // Set backlog to 0 to make sure that queue size will be minimum.
4442 // In Linux, because the minimum queue will be 1, connect() will be blocked
4443 // if the other clients already called connect() and the connection request was not accepted.
4444 if (listen(s, 0) < 0) {
4445 MYLOGE("listen(control socket): %s\n", strerror(errno));
4446 return -1;
4447 }
4448
4449 struct sockaddr addr;
4450 socklen_t alen = sizeof(addr);
Abhijeet Kaur2113cae2019-09-13 09:24:15 +01004451 int fd = accept4(s, &addr, &alen, SOCK_CLOEXEC);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004452
4453 // Close socket just after accept(), to make sure that connect() by client will get error
4454 // when the socket is used by the other services.
4455 // There is still a race condition possibility between accept and close, but there is no way
4456 // to close-on-accept atomically.
4457 // See detail; b/123306389#comment25
4458 close(s);
4459
4460 if (fd < 0) {
4461 MYLOGE("accept(control socket): %s\n", strerror(errno));
4462 return -1;
4463 }
4464
4465 return fd;
4466}
4467
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004468// TODO: should call is_valid_output_file and/or be merged into it.
4469void create_parent_dirs(const char *path) {
4470 char *chp = const_cast<char *> (path);
4471
4472 /* skip initial slash */
4473 if (chp[0] == '/')
4474 chp++;
4475
4476 /* create leading directories, if necessary */
4477 struct stat dir_stat;
4478 while (chp && chp[0]) {
4479 chp = strchr(chp, '/');
4480 if (chp) {
4481 *chp = 0;
4482 if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
4483 MYLOGI("Creating directory %s\n", path);
4484 if (mkdir(path, 0770)) { /* drwxrwx--- */
4485 MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
4486 } else if (chown(path, AID_SHELL, AID_SHELL)) {
4487 MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
4488 }
4489 }
4490 *chp++ = '/';
4491 }
4492 }
4493}
4494
4495bool _redirect_to_file(FILE* redirect, char* path, int truncate_flag) {
4496 create_parent_dirs(path);
4497
4498 int fd = TEMP_FAILURE_RETRY(open(path,
4499 O_WRONLY | O_CREAT | truncate_flag | O_CLOEXEC | O_NOFOLLOW,
4500 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
4501 if (fd < 0) {
4502 MYLOGE("%s: %s\n", path, strerror(errno));
4503 return false;
4504 }
4505
4506 TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
4507 close(fd);
4508 return true;
4509}
4510
4511bool redirect_to_file(FILE* redirect, char* path) {
4512 return _redirect_to_file(redirect, path, O_TRUNC);
4513}
4514
4515bool redirect_to_existing_file(FILE* redirect, char* path) {
4516 return _redirect_to_file(redirect, path, O_APPEND);
4517}
4518
4519void dump_route_tables() {
4520 DurationReporter duration_reporter("DUMP ROUTE TABLES");
4521 if (PropertiesHelper::IsDryRun()) return;
4522 const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
4523 ds.DumpFile("RT_TABLES", RT_TABLES_PATH);
4524 FILE* fp = fopen(RT_TABLES_PATH, "re");
4525 if (!fp) {
4526 printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
4527 return;
4528 }
4529 char table[16];
4530 // Each line has an integer (the table number), a space, and a string (the table name). We only
4531 // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
4532 // Add a fixed max limit so this doesn't go awry.
4533 for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
4534 RunCommand("ROUTE TABLE IPv4", {"ip", "-4", "route", "show", "table", table});
4535 RunCommand("ROUTE TABLE IPv6", {"ip", "-6", "route", "show", "table", table});
4536 }
4537 fclose(fp);
4538}
4539
Li Li830179f2022-01-04 12:53:29 -08004540void dump_frozen_cgroupfs(const char *dir, int level,
4541 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4542 DIR *dirp;
4543 struct dirent *d;
4544 char *newpath = nullptr;
4545
4546 dirp = opendir(dir);
4547 if (dirp == nullptr) {
4548 MYLOGE("%s: %s\n", dir, strerror(errno));
4549 return;
4550 }
4551
4552 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4553 if ((d->d_name[0] == '.')
4554 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4555 || (d->d_name[1] == '\0'))) {
4556 continue;
4557 }
4558 if (d->d_type == DT_DIR) {
4559 asprintf(&newpath, "%s/%s/", dir, d->d_name);
4560 if (!newpath) {
4561 continue;
4562 }
4563 if (level == 0 && !strncmp(d->d_name, "uid_", 4)) {
4564 dump_frozen_cgroupfs(newpath, 1, dump_from_fd);
4565 } else if (level == 1 && !strncmp(d->d_name, "pid_", 4)) {
4566 char *freezer = nullptr;
4567 asprintf(&freezer, "%s/%s", newpath, "cgroup.freeze");
4568 if (freezer) {
4569 FILE* fp = fopen(freezer, "r");
4570 if (fp != NULL) {
4571 int frozen;
4572 fscanf(fp, "%d", &frozen);
4573 if (frozen > 0) {
4574 dump_files("", newpath, skip_none, dump_from_fd);
4575 }
4576 fclose(fp);
4577 }
4578 free(freezer);
4579 }
4580 }
4581 }
4582 }
4583 closedir(dirp);
4584}
4585
4586void dump_frozen_cgroupfs() {
Li Li830179f2022-01-04 12:53:29 -08004587 MYLOGD("Adding frozen processes from %s\n", CGROUPFS_DIR);
4588 DurationReporter duration_reporter("FROZEN CGROUPFS");
4589 if (PropertiesHelper::IsDryRun()) return;
4590 dump_frozen_cgroupfs(CGROUPFS_DIR, 0, _add_file_from_fd);
4591}
4592
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004593void Dumpstate::UpdateProgress(int32_t delta_sec) {
4594 if (progress_ == nullptr) {
4595 MYLOGE("UpdateProgress: progress_ not set\n");
4596 return;
4597 }
Rhed Jaobf63d8a2020-07-21 15:42:55 +08004598 // This function updates progress related members of the dumpstate and reports
4599 // progress percentage to the bugreport client. Since it could be called by
4600 // different dump tasks at the same time if the parallel run is enabled, a
4601 // mutex lock is necessary here to synchronize the call.
4602 std::lock_guard<std::recursive_mutex> lock(mutex_);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004603
4604 // Always update progess so stats can be tuned...
Nandana Dutt402a8392019-06-14 14:25:13 +01004605 progress_->Inc(delta_sec);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004606
4607 // ...but only notifiy listeners when necessary.
4608 if (!options_->do_progress_updates) return;
4609
4610 int progress = progress_->Get();
4611 int max = progress_->GetMax();
Nandana Dutt402a8392019-06-14 14:25:13 +01004612 int percent = 100 * progress / max;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004613
Nandana Dutt402a8392019-06-14 14:25:13 +01004614 if (last_reported_percent_progress_ > 0 && percent <= last_reported_percent_progress_) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004615 return;
4616 }
Nandana Dutt402a8392019-06-14 14:25:13 +01004617 last_reported_percent_progress_ = percent;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004618
4619 if (control_socket_fd_ >= 0) {
4620 dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
4621 fsync(control_socket_fd_);
4622 }
4623
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004624 if (listener_ != nullptr) {
Nandana Dutt235c6672019-11-14 15:22:32 +00004625 if (percent % 10 == 0) {
4626 // We don't want to spam logcat, so only log multiples of 10.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004627 MYLOGD("Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004628 } else {
4629 // stderr is ignored on normal invocations, but useful when calling
4630 // /system/bin/dumpstate directly for debuggging.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004631 fprintf(stderr, "Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004632 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004633
4634 listener_->onProgress(percent);
4635 }
4636}
4637
4638void Dumpstate::TakeScreenshot(const std::string& path) {
4639 const std::string& real_path = path.empty() ? screenshot_path_ : path;
4640 int status =
4641 RunCommand("", {"/system/bin/screencap", "-p", real_path},
4642 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
4643 if (status == 0) {
4644 MYLOGD("Screenshot saved on %s\n", real_path.c_str());
4645 } else {
4646 MYLOGE("Failed to take screenshot on %s\n", real_path.c_str());
4647 }
Paul Chang0d2aad72020-02-13 20:04:03 +08004648 if (listener_ != nullptr) {
4649 // Show a visual indication to indicate screenshot is taken via
4650 // IDumpstateListener.onScreenshotTaken()
4651 listener_->onScreenshotTaken(status == 0);
4652 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004653}
4654
4655bool is_dir(const char* pathname) {
4656 struct stat info;
4657 if (stat(pathname, &info) == -1) {
4658 return false;
4659 }
4660 return S_ISDIR(info.st_mode);
4661}
4662
4663time_t get_mtime(int fd, time_t default_mtime) {
4664 struct stat info;
4665 if (fstat(fd, &info) == -1) {
4666 return default_mtime;
4667 }
4668 return info.st_mtime;
4669}