blob: 24b4b0de93320283f1c7c350966828045b2a7141 [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
Felipe Lemee82a27d2016-01-05 13:35:44 -0800173#define RECOVERY_DIR "/cache/recovery"
Mark Salyzynd6ab0112016-03-25 12:56:39 -0700174#define RECOVERY_DATA_DIR "/data/misc/recovery"
Tianjie Xu75d53362018-04-11 16:42:28 -0700175#define UPDATE_ENGINE_LOG_DIR "/data/misc/update_engine_log"
Kelvin Zhang6eaa0f92022-09-12 09:29:19 -0700176#define UPDATE_ENGINE_PREF_DIR "/data/misc/update_engine/prefs"
Mark Salyzyn4d42dea2016-04-01 10:03:14 -0700177#define LOGPERSIST_DATA_DIR "/data/misc/logd"
Jerry Changa1df8a92020-01-02 16:03:39 +0800178#define PREREBOOT_DATA_DIR "/data/misc/prereboot"
David Brazdild2991962016-06-03 14:40:44 +0100179#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
180#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
Benedict Wong8f9d8a42019-01-03 16:19:38 -0800181#define XFRM_STAT_PROC_FILE "/proc/net/xfrm_stat"
Steven Moreland9379c462023-12-21 02:04:27 +0000182#define KERNEL_CONFIG "/proc/config.gz"
Erik Kline08165202016-05-30 11:55:44 +0900183#define WLUTIL "/vendor/xbin/wlutil"
Vishnu Nair36b4cdb2017-11-17 10:27:05 -0800184#define WMTRACE_DATA_DIR "/data/misc/wmtrace"
Yifan Hong3945e1b2019-10-29 12:59:23 -0700185#define OTA_METADATA_DIR "/metadata/ota"
Yifan Hong0efa7972020-02-03 16:45:02 -0800186#define SNAPSHOTCTL_LOG_DIR "/data/misc/snapshotctl_log"
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +0900187#define LINKERCONFIG_DIR "/linkerconfig"
Calin Juravlef84d3692020-04-28 15:31:12 -0700188#define PACKAGE_DEX_USE_LIST "/data/system/package-dex-usage.list"
Primiano Tuccifaaaafb2021-01-14 12:26:29 +0000189#define SYSTEM_TRACE_SNAPSHOT "/data/misc/perfetto-traces/bugreport/systrace.pftrace"
Li Li2eedd412021-06-30 15:11:53 -0700190#define CGROUPFS_DIR "/sys/fs/cgroup"
MÃ¥rten Kongstad60195a72022-09-20 14:14:20 +0200191#define SDK_EXT_INFO "/apex/com.android.sdkext/bin/derive_sdk"
Jeff Sharkey9df29d52023-02-06 14:26:30 -0700192#define DROPBOX_DIR "/data/system/dropbox"
MÃ¥rten Kongstad5ad813f2023-09-28 10:09:18 +0200193#define PRINT_FLAGS "/system/bin/printflags"
Nattharat Jariyanuntanaetb250cae2024-05-15 07:48:19 +0000194#define UWB_LOG_DIR "/data/misc/apexdata/com.android.uwb/log"
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700195
Narayan Kamath8f788292017-05-25 13:20:39 +0100196// TODO(narayan): Since this information has to be kept in sync
197// with tombstoned, we should just put it in a common header.
198//
199// File: system/core/debuggerd/tombstoned/tombstoned.cpp
Narayan Kamathbd863722017-06-01 18:50:12 +0100200static const std::string TOMBSTONE_DIR = "/data/tombstones/";
201static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
202static const std::string ANR_DIR = "/data/anr/";
203static const std::string ANR_FILE_PREFIX = "anr_";
Andy Hungd62f7e62024-01-11 15:47:52 -0800204static const std::string ANR_TRACE_FILE_PREFIX = "trace_";
Woody Lin20767a92022-11-29 15:50:24 +0800205static const std::string SHUTDOWN_CHECKPOINTS_DIR = "/data/system/shutdown-checkpoints/";
206static const std::string SHUTDOWN_CHECKPOINTS_FILE_PREFIX = "checkpoints-";
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700207
Felipe Lemee844a9d2016-09-21 15:01:39 -0700208// TODO: temporary variables and functions used during C++ refactoring
Nandana Dutt979388e2018-11-30 16:48:55 +0000209
Nandana Dutt5c390032019-03-12 10:52:56 +0000210#define RETURN_IF_USER_DENIED_CONSENT() \
211 if (ds.IsUserConsentDenied()) { \
212 MYLOGE("Returning early as user denied consent to share bugreport with calling app."); \
213 return Dumpstate::RunStatus::USER_CONSENT_DENIED; \
214 }
215
216// Runs func_ptr, but checks user consent before and after running it. Returns USER_CONSENT_DENIED
217// if consent is found to be denied.
218#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(func_ptr, ...) \
219 RETURN_IF_USER_DENIED_CONSENT(); \
220 func_ptr(__VA_ARGS__); \
221 RETURN_IF_USER_DENIED_CONSENT();
222
Rhed Jao5377d792020-07-16 17:37:39 +0800223// Runs func_ptr, and logs a duration report after it's finished.
224#define RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, ...) \
225 { \
226 DurationReporter duration_reporter_in_macro(log_title); \
227 func_ptr(__VA_ARGS__); \
228 }
229
230// Similar with RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK, an additional duration report
231// is output after a slow function is finished.
232#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(log_title, func_ptr, ...) \
233 RETURN_IF_USER_DENIED_CONSENT(); \
234 RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, __VA_ARGS__); \
235 RETURN_IF_USER_DENIED_CONSENT();
236
Chris Morinbc223142022-02-04 14:17:11 -0800237#define WAIT_TASK_WITH_CONSENT_CHECK(future) \
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800238 RETURN_IF_USER_DENIED_CONSENT(); \
Chris Morinbc223142022-02-04 14:17:11 -0800239 WaitForTask(future); \
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800240 RETURN_IF_USER_DENIED_CONSENT();
241
Sahana Raof35ed432019-07-12 10:47:52 +0100242static const char* WAKE_LOCK_NAME = "dumpstate_wakelock";
243
Rhed Jao5377d792020-07-16 17:37:39 +0800244// Names of parallel tasks, they are used for the DumpPool to identify the dump
245// task and the log title of the duration report.
246static const std::string DUMP_TRACES_TASK = "DUMP TRACES";
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800247static const std::string DUMP_INCIDENT_REPORT_TASK = "INCIDENT REPORT";
Aaron Huanga99452a2022-04-27 18:51:16 +0800248static const std::string DUMP_NETSTATS_PROTO_TASK = "DUMP NETSTATS PROTO";
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800249static const std::string DUMP_HALS_TASK = "DUMP HALS";
250static const std::string DUMP_BOARD_TASK = "dumpstate_board()";
Rhed Jaoe017f982020-07-21 17:58:41 +0800251static const std::string DUMP_CHECKINS_TASK = "DUMP CHECKINS";
Kean Mariottica20f2d2023-12-15 09:34:25 +0000252static const std::string SERIALIZE_PERFETTO_TRACE_TASK = "SERIALIZE PERFETTO TRACE";
Rhed Jao5377d792020-07-16 17:37:39 +0800253
Nandana Dutt979388e2018-11-30 16:48:55 +0000254namespace android {
255namespace os {
256namespace {
257
258static int Open(std::string path, int flags, mode_t mode = 0) {
259 int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
260 if (fd == -1) {
261 MYLOGE("open(%s, %s)\n", path.c_str(), strerror(errno));
262 }
263 return fd;
264}
265
mhasank2d75c442020-06-11 15:05:25 -0700266static int OpenForWrite(std::string path) {
267 return Open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
268 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
269}
Nandana Dutt979388e2018-11-30 16:48:55 +0000270
271static int OpenForRead(std::string path) {
272 return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
273}
274
275bool CopyFile(int in_fd, int out_fd) {
276 char buf[4096];
277 ssize_t byte_count;
278 while ((byte_count = TEMP_FAILURE_RETRY(read(in_fd, buf, sizeof(buf)))) > 0) {
279 if (!android::base::WriteFully(out_fd, buf, byte_count)) {
280 return false;
281 }
282 }
283 return (byte_count != -1);
284}
285
286static bool CopyFileToFd(const std::string& input_file, int out_fd) {
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000287 MYLOGD("Going to copy file (%s) to %d\n", input_file.c_str(), out_fd);
Nandana Dutt979388e2018-11-30 16:48:55 +0000288
289 // Obtain a handle to the source file.
290 android::base::unique_fd in_fd(OpenForRead(input_file));
291 if (out_fd != -1 && in_fd.get() != -1) {
292 if (CopyFile(in_fd.get(), out_fd)) {
293 return true;
294 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000295 MYLOGE("Failed to copy file: %s\n", strerror(errno));
Nandana Dutt979388e2018-11-30 16:48:55 +0000296 }
297 return false;
298}
299
Nandana Duttd2f5f082019-01-18 17:13:52 +0000300static bool UnlinkAndLogOnError(const std::string& file) {
Nandana Dutt8ae16e62020-03-27 10:20:22 +0000301 if (file.empty()) {
302 return false;
303 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000304 if (unlink(file.c_str())) {
305 MYLOGE("Failed to unlink file (%s): %s\n", file.c_str(), strerror(errno));
Nandana Duttd2f5f082019-01-18 17:13:52 +0000306 return false;
307 }
308 return true;
309}
Nandana Dutt979388e2018-11-30 16:48:55 +0000310
Nikita Ioffea325a572019-05-16 19:49:47 +0100311int64_t GetModuleMetadataVersion() {
312 auto binder = defaultServiceManager()->getService(android::String16("package_native"));
313 if (binder == nullptr) {
314 MYLOGE("Failed to retrieve package_native service");
315 return 0L;
316 }
317 auto package_service = android::interface_cast<content::pm::IPackageManagerNative>(binder);
318 std::string package_name;
319 auto status = package_service->getModuleMetadataPackageName(&package_name);
320 if (!status.isOk()) {
321 MYLOGE("Failed to retrieve module metadata package name: %s", status.toString8().c_str());
322 return 0L;
323 }
Nandana Duttdb379fa2019-10-09 16:54:41 +0100324 MYLOGD("Module metadata package name: %s\n", package_name.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100325 int64_t version_code;
326 status = package_service->getVersionCodeForPackage(android::String16(package_name.c_str()),
327 &version_code);
328 if (!status.isOk()) {
329 MYLOGE("Failed to retrieve module metadata version: %s", status.toString8().c_str());
330 return 0L;
331 }
332 return version_code;
333}
334
mhasank2d75c442020-06-11 15:05:25 -0700335static bool PathExists(const std::string& path) {
336 struct stat sb;
337 return stat(path.c_str(), &sb) == 0;
338}
339
340static bool CopyFileToFile(const std::string& input_file, const std::string& output_file) {
341 if (input_file == output_file) {
342 MYLOGD("Skipping copying bugreport file since the destination is the same (%s)\n",
343 output_file.c_str());
344 return false;
345 }
346 else if (PathExists(output_file)) {
347 MYLOGD("Cannot overwrite an existing file (%s)\n", output_file.c_str());
348 return false;
349 }
350
351 MYLOGD("Going to copy bugreport file (%s) to %s\n", input_file.c_str(), output_file.c_str());
352 android::base::unique_fd out_fd(OpenForWrite(output_file));
353 return CopyFileToFd(input_file, out_fd.get());
354}
355
Nandana Dutt979388e2018-11-30 16:48:55 +0000356} // namespace
357} // namespace os
358} // namespace android
359
Felipe Leme678727a2016-09-21 17:22:11 -0700360static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
Felipe Lemebda15a02016-11-16 17:48:25 -0800361 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
Rhed Jaoe017f982020-07-21 17:58:41 +0800362 long dumpsysTimeoutMs = 0, int out_fd = STDOUT_FILENO) {
363 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs, out_fd);
364}
365static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
366 int out_fd) {
367 return ds.RunDumpsys(title, dumpsysArgs, Dumpstate::DEFAULT_DUMPSYS, 0, out_fd);
Felipe Leme678727a2016-09-21 17:22:11 -0700368}
369static int DumpFile(const std::string& title, const std::string& path) {
370 return ds.DumpFile(title, path);
371}
Felipe Lemee82a27d2016-01-05 13:35:44 -0800372
Felipe Lemee844a9d2016-09-21 15:01:39 -0700373// Relative directory (inside the zip) for all files copied as-is into the bugreport.
374static const std::string ZIP_ROOT_DIR = "FS";
375
Vishnu Naire97d6122018-01-18 13:58:56 -0800376static const std::string kProtoPath = "proto/";
377static const std::string kProtoExt = ".proto";
Jie Song9fbfad02017-06-20 16:29:42 -0700378static const std::string kDumpstateBoardFiles[] = {
379 "dumpstate_board.txt",
Felipe Leme95d6ca52017-08-01 16:35:56 -0700380 "dumpstate_board.bin"
Jie Song9fbfad02017-06-20 16:29:42 -0700381};
382static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
383
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700384static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Lemed071c682016-10-20 16:48:00 -0700385static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700386
Felipe Lemef0292972016-11-22 13:57:05 -0800387static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
388
Narayan Kamath8f788292017-05-25 13:20:39 +0100389/*
Narayan Kamathbd863722017-06-01 18:50:12 +0100390 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
Rhed Jao01dc0c62020-06-03 17:13:30 +0800391 * The returned vector is sorted by the mtimes of the dumps with descending
Chris Morinc2cba7a2022-02-01 17:06:50 -0800392 * order.
Narayan Kamath8f788292017-05-25 13:20:39 +0100393 */
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700394static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
Chris Morinc2cba7a2022-02-01 17:06:50 -0800395 const std::string& file_prefix) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100396 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100397
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700398 if (dump_dir == nullptr) {
399 MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno));
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700400 return std::vector<DumpData>();
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700401 }
402
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700403 std::vector<DumpData> dump_data;
Narayan Kamathbd863722017-06-01 18:50:12 +0100404 struct dirent* entry = nullptr;
405 while ((entry = readdir(dump_dir.get()))) {
406 if (entry->d_type != DT_REG) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100407 continue;
408 }
409
Narayan Kamathbd863722017-06-01 18:50:12 +0100410 const std::string base_name(entry->d_name);
411 if (base_name.find(file_prefix) != 0) {
412 continue;
413 }
414
415 const std::string abs_path = dir_path + base_name;
416 android::base::unique_fd fd(
417 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
418 if (fd == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700419 MYLOGW("Unable to open dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamathbd863722017-06-01 18:50:12 +0100420 break;
421 }
422
423 struct stat st = {};
424 if (fstat(fd, &st) == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700425 MYLOGW("Unable to stat dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamath8f788292017-05-25 13:20:39 +0100426 continue;
427 }
428
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700429 dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700430 }
Rhed Jao01dc0c62020-06-03 17:13:30 +0800431 if (!dump_data.empty()) {
432 std::sort(dump_data.begin(), dump_data.end(),
433 [](const auto& a, const auto& b) { return a.mtime > b.mtime; });
434 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100435
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700436 return dump_data;
Narayan Kamath8f788292017-05-25 13:20:39 +0100437}
438
Narayan Kamathbd863722017-06-01 18:50:12 +0100439static bool AddDumps(const std::vector<DumpData>::const_iterator start,
440 const std::vector<DumpData>::const_iterator end,
441 const char* type_name, const bool add_to_zip) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100442 bool dumped = false;
Narayan Kamathbd863722017-06-01 18:50:12 +0100443 for (auto it = start; it != end; ++it) {
444 const std::string& name = it->name;
445 const int fd = it->fd;
Narayan Kamath8f788292017-05-25 13:20:39 +0100446 dumped = true;
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100447
448 // Seek to the beginning of the file before dumping any data. A given
449 // DumpData entry might be dumped multiple times in the report.
450 //
451 // For example, the most recent ANR entry is dumped to the body of the
452 // main entry and it also shows up as a separate entry in the bugreport
453 // ZIP file.
454 if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) {
455 MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(),
456 strerror(errno));
457 }
458
Chris Morinc2cba7a2022-02-01 17:06:50 -0800459 if (add_to_zip) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800460 if (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd, /* timeout = */ 0ms) != OK) {
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100461 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100462 }
463 } else {
464 dump_file_from_fd(type_name, name.c_str(), fd);
465 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100466 }
467
468 return dumped;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700469}
470
Felipe Leme635ca312016-01-05 14:23:02 -0800471// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700472void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800473 char path[PATH_MAX];
474
475 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
476 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700477 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800478 char linkname[PATH_MAX];
479 ssize_t r = readlink(path, linkname, PATH_MAX);
480 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800481 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800482 return;
483 }
484 linkname[r] = '\0';
485
486 if (mount_points.find(linkname) == mount_points.end()) {
487 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700488 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700489 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
Felipe Leme635ca312016-01-05 14:23:02 -0800490 mount_points.insert(linkname);
491 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800492 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800493 }
494 }
495}
496
497void add_mountinfo() {
Felipe Leme678727a2016-09-21 17:22:11 -0700498 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800499 mount_points.clear();
Felipe Leme46b85da2016-11-21 17:40:45 -0800500 DurationReporter duration_reporter(title, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700501 for_each_pid(do_mountinfo, nullptr);
502 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800503}
504
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700505static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
506{
507 DIR *d;
508 struct dirent *de;
509 char path[PATH_MAX];
510
511 d = opendir(driverpath);
Yi Kong19d5c002018-07-20 13:39:55 -0700512 if (d == nullptr) {
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700513 return;
514 }
515
516 while ((de = readdir(d))) {
517 if (de->d_type != DT_LNK) {
518 continue;
519 }
520 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700521 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700522 }
523
524 closedir(d);
525}
526
Mark Salyzyn326842f2015-04-30 09:49:41 -0700527static bool skip_not_stat(const char *path) {
528 static const char stat[] = "/stat";
529 size_t len = strlen(path);
530 if (path[len - 1] == '/') { /* Directory? */
531 return false;
532 }
533 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
534}
535
Jeff Sharkey9df29d52023-02-06 14:26:30 -0700536static bool skip_wtf_strictmode(const char *path) {
537 if (strstr(path, "_wtf")) {
538 return true;
539 } else if (strstr(path, "_strictmode")) {
540 return true;
541 }
542 return false;
543}
544
Felipe Leme4c2d6632016-09-28 14:32:00 -0700545static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800546 return false;
547}
548
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700549unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700550
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800551//
552// stat offsets
553// Name units description
554// ---- ----- -----------
555// read I/Os requests number of read I/Os processed
556#define __STAT_READ_IOS 0
557// read merges requests number of read I/Os merged with in-queue I/O
558#define __STAT_READ_MERGES 1
559// read sectors sectors number of sectors read
560#define __STAT_READ_SECTORS 2
561// read ticks milliseconds total wait time for read requests
562#define __STAT_READ_TICKS 3
563// write I/Os requests number of write I/Os processed
564#define __STAT_WRITE_IOS 4
565// write merges requests number of write I/Os merged with in-queue I/O
566#define __STAT_WRITE_MERGES 5
567// write sectors sectors number of sectors written
568#define __STAT_WRITE_SECTORS 6
569// write ticks milliseconds total wait time for write requests
570#define __STAT_WRITE_TICKS 7
571// in_flight requests number of I/Os currently in flight
572#define __STAT_IN_FLIGHT 8
573// io_ticks milliseconds total time this block device has been active
574#define __STAT_IO_TICKS 9
575// time_in_queue milliseconds total wait time for all requests
576#define __STAT_IN_QUEUE 10
577#define __STAT_NUMBER_FIELD 11
578//
579// read I/Os, write I/Os
580// =====================
581//
582// These values increment when an I/O request completes.
583//
584// read merges, write merges
585// =========================
586//
587// These values increment when an I/O request is merged with an
588// already-queued I/O request.
589//
590// read sectors, write sectors
591// ===========================
592//
593// These values count the number of sectors read from or written to this
594// block device. The "sectors" in question are the standard UNIX 512-byte
595// sectors, not any device- or filesystem-specific block size. The
596// counters are incremented when the I/O completes.
597#define SECTOR_SIZE 512
598//
599// read ticks, write ticks
600// =======================
601//
602// These values count the number of milliseconds that I/O requests have
603// waited on this block device. If there are multiple I/O requests waiting,
604// these values will increase at a rate greater than 1000/second; for
605// example, if 60 read requests wait for an average of 30 ms, the read_ticks
606// field will increase by 60*30 = 1800.
607//
608// in_flight
609// =========
610//
611// This value counts the number of I/O requests that have been issued to
612// the device driver but have not yet completed. It does not include I/O
613// requests that are in the queue but not yet issued to the device driver.
614//
615// io_ticks
616// ========
617//
618// This value counts the number of milliseconds during which the device has
619// had I/O requests queued.
620//
621// time_in_queue
622// =============
623//
624// This value counts the number of milliseconds that I/O requests have waited
625// on this block device. If there are multiple I/O requests waiting, this
626// value will increase as the product of the number of milliseconds times the
627// number of requests waiting (see "read ticks" above for an example).
628#define S_TO_MS 1000
629//
630
Mark Salyzyn326842f2015-04-30 09:49:41 -0700631static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800632 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700633 bool z;
Yi Kong19d5c002018-07-20 13:39:55 -0700634 char *cp, *buffer = nullptr;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700635 size_t i = 0;
Josh Gao7c4258c2018-06-25 13:40:08 -0700636 FILE *fp = fdopen(dup(fd), "rb");
Mark Salyzyn326842f2015-04-30 09:49:41 -0700637 getline(&buffer, &i, fp);
638 fclose(fp);
639 if (!buffer) {
640 return -errno;
641 }
642 i = strlen(buffer);
643 while ((i > 0) && (buffer[i - 1] == '\n')) {
644 buffer[--i] = '\0';
645 }
646 if (!*buffer) {
647 free(buffer);
648 return 0;
649 }
650 z = true;
651 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800652 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700653 if (fields[i] != 0) {
654 z = false;
655 }
656 }
657 if (z) { /* never accessed */
658 free(buffer);
659 return 0;
660 }
661
Wei Wang509bb5d2017-06-09 14:42:12 -0700662 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
663 path += sizeof(BLK_DEV_SYS_DIR) - 1;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700664 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700665
666 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
667 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
668 "W-wait", "in-fli", "activ", "T-wait", path, buffer);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700669 free(buffer);
670
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800671 if (fields[__STAT_IO_TICKS]) {
672 unsigned long read_perf = 0;
673 unsigned long read_ios = 0;
674 if (fields[__STAT_READ_TICKS]) {
675 unsigned long long divisor = fields[__STAT_READ_TICKS]
676 * fields[__STAT_IO_TICKS];
677 read_perf = ((unsigned long long)SECTOR_SIZE
678 * fields[__STAT_READ_SECTORS]
679 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
680 / divisor;
681 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
682 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
683 / divisor;
684 }
685
686 unsigned long write_perf = 0;
687 unsigned long write_ios = 0;
688 if (fields[__STAT_WRITE_TICKS]) {
689 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
690 * fields[__STAT_IO_TICKS];
691 write_perf = ((unsigned long long)SECTOR_SIZE
692 * fields[__STAT_WRITE_SECTORS]
693 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
694 / divisor;
695 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
696 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
697 / divisor;
698 }
699
700 unsigned queue = (fields[__STAT_IN_QUEUE]
701 + (fields[__STAT_IO_TICKS] >> 1))
702 / fields[__STAT_IO_TICKS];
703
704 if (!write_perf && !write_ios) {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700705 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 -0800706 } else {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700707 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 -0800708 read_ios, write_perf, write_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800709 }
710
711 /* bugreport timeout factor adjustment */
712 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
713 worst_write_perf = write_perf;
714 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700715 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700716 return 0;
717}
718
Yao Chenbe3bbc12018-01-17 16:31:10 -0800719static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
720
Tom Cherryf4472f32020-08-05 09:31:17 -0700721// Returns the actual readable size of the given buffer or -1 on error.
722static long logcat_buffer_readable_size(const std::string& buffer) {
723 std::unique_ptr<logger_list, decltype(&android_logger_list_free)> logger_list{
724 android_logger_list_alloc(0, 0, 0), &android_logger_list_free};
725 auto logger = android_logger_open(logger_list.get(), android_name_to_log_id(buffer.c_str()));
726
727 return android_logger_get_log_readable_size(logger);
728}
729
730// Returns timeout in ms to read a list of buffers.
Yao Chenbe3bbc12018-01-17 16:31:10 -0800731static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
732 unsigned long timeout_ms = 0;
733 for (const auto& buffer : buffers) {
Tom Cherryf4472f32020-08-05 09:31:17 -0700734 long readable_size = logcat_buffer_readable_size(buffer);
735 if (readable_size > 0) {
736 // Engineering margin is ten-fold our guess.
737 timeout_ms += 10 * (readable_size + worst_write_perf) / worst_write_perf;
738 }
Yao Chenbe3bbc12018-01-17 16:31:10 -0800739 }
740 return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700741}
742
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800743// Opens a socket and returns its file descriptor.
744static int open_socket(const char* service);
745
Nandana Duttd2f5f082019-01-18 17:13:52 +0000746Dumpstate::ConsentCallback::ConsentCallback() : result_(UNAVAILABLE), start_time_(Nanotime()) {
747}
748
749android::binder::Status Dumpstate::ConsentCallback::onReportApproved() {
750 std::lock_guard<std::mutex> lock(lock_);
751 result_ = APPROVED;
752 MYLOGD("User approved consent to share bugreport\n");
Paul Chang0d2aad72020-02-13 20:04:03 +0800753
754 // Maybe copy screenshot so calling app can display the screenshot to the user as soon as
755 // consent is granted.
756 if (ds.options_->is_screenshot_copied) {
757 return android::binder::Status::ok();
758 }
759
760 if (!ds.options_->do_screenshot || ds.options_->screenshot_fd.get() == -1 ||
761 !ds.do_early_screenshot_) {
762 return android::binder::Status::ok();
763 }
764
765 bool copy_succeeded = android::os::CopyFileToFd(ds.screenshot_path_,
766 ds.options_->screenshot_fd.get());
767 ds.options_->is_screenshot_copied = copy_succeeded;
768 if (copy_succeeded) {
769 android::os::UnlinkAndLogOnError(ds.screenshot_path_);
770 }
Nandana Duttd2f5f082019-01-18 17:13:52 +0000771 return android::binder::Status::ok();
772}
773
774android::binder::Status Dumpstate::ConsentCallback::onReportDenied() {
775 std::lock_guard<std::mutex> lock(lock_);
776 result_ = DENIED;
777 MYLOGW("User denied consent to share bugreport\n");
778 return android::binder::Status::ok();
779}
780
781UserConsentResult Dumpstate::ConsentCallback::getResult() {
782 std::lock_guard<std::mutex> lock(lock_);
783 return result_;
784}
785
786uint64_t Dumpstate::ConsentCallback::getElapsedTimeMs() const {
Hunter Knepshieldf0a39052020-01-03 14:53:04 -0800787 return (Nanotime() - start_time_) / NANOS_PER_MILLI;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000788}
789
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700790void Dumpstate::PrintHeader() const {
MÃ¥rten Kongstad60195a72022-09-20 14:14:20 +0200791 std::string build, fingerprint, radio, bootloader, network, sdkversion;
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700792 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700793
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700794 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
795 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700796 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
797 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
798 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
MÃ¥rten Kongstad60195a72022-09-20 14:14:20 +0200799 sdkversion = android::base::GetProperty("ro.build.version.sdk", "(unknown)");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700800 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
Colin Crossf45fa6b2012-03-26 12:38:26 -0700801
Felipe Lemed8b94e52016-12-08 10:21:44 -0800802 printf("========================================================\n");
803 printf("== dumpstate: %s\n", date);
804 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700805
Felipe Lemed8b94e52016-12-08 10:21:44 -0800806 printf("\n");
807 printf("Build: %s\n", build.c_str());
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700808 // NOTE: fingerprint entry format is important for other tools.
Felipe Lemed8b94e52016-12-08 10:21:44 -0800809 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
810 printf("Bootloader: %s\n", bootloader.c_str());
811 printf("Radio: %s\n", radio.c_str());
812 printf("Network: %s\n", network.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100813 int64_t module_metadata_version = android::os::GetModuleMetadataVersion();
814 if (module_metadata_version != 0) {
815 printf("Module Metadata version: %" PRId64 "\n", module_metadata_version);
816 }
MÃ¥rten Kongstad60195a72022-09-20 14:14:20 +0200817 printf("Android SDK version: %s\n", sdkversion.c_str());
818 printf("SDK extensions: ");
819 RunCommandToFd(STDOUT_FILENO, "", {SDK_EXT_INFO, "--header"},
820 CommandOptions::WithTimeout(1).Always().DropRoot().Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700821
Felipe Lemed8b94e52016-12-08 10:21:44 -0800822 printf("Kernel: ");
Felipe Lemef0292972016-11-22 13:57:05 -0800823 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
Felipe Lemed8b94e52016-12-08 10:21:44 -0800824 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
Devin Moore09fde8d2023-03-21 16:28:22 +0000825 printf("Bootconfig: ");
826 DumpFileToFd(STDOUT_FILENO, "", "/proc/bootconfig");
Felipe Leme7709f8a2017-12-05 09:30:09 -0800827 printf("Uptime: ");
828 RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"},
829 CommandOptions::WithTimeout(1).Always().Build());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800830 printf("Bugreport format version: %s\n", version_.c_str());
Kevin Jeonfa64e642023-07-27 11:36:41 -0400831 printf(
832 "Dumpstate info: id=%d pid=%d dry_run=%d parallel_run=%d strict_run=%d args=%s "
833 "bugreport_mode=%s\n",
834 id_, pid_, PropertiesHelper::IsDryRun(), PropertiesHelper::IsParallelRun(),
835 PropertiesHelper::IsStrictRun(), options_->args.c_str(),
836 options_->bugreport_mode_string.c_str());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800837 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800838}
839
Felipe Leme24b66ee2016-06-16 10:55:26 -0700840// List of file extensions that can cause a zip file attachment to be rejected by some email
841// service providers.
842static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
843 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
844 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
845 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
846};
847
Vishnu Naire97d6122018-01-18 13:58:56 -0800848status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd,
849 std::chrono::milliseconds timeout = 0ms) {
Felipe Leme24b66ee2016-06-16 10:55:26 -0700850 std::string valid_name = entry_name;
851
852 // Rename extension if necessary.
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -0700853 size_t idx = entry_name.rfind('.');
Felipe Leme24b66ee2016-06-16 10:55:26 -0700854 if (idx != std::string::npos) {
855 std::string extension = entry_name.substr(idx);
856 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
857 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
858 valid_name = entry_name + ".renamed";
859 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
860 }
861 }
862
Felipe Leme6fe9db62016-02-12 09:04:16 -0800863 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
864 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Kevin Jeon9bbe0ac2022-05-05 22:05:43 +0000865 size_t flags = ZipWriter::kCompress | ZipWriter::kDefaultCompression;
866 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), flags,
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700867 get_mtime(fd, ds.now_));
Felipe Leme1d486fe2016-10-14 18:06:47 -0700868 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700869 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700870 ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800871 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800872 }
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000873 bool finished_entry = false;
874 auto finish_entry = [this, &finished_entry] {
875 if (!finished_entry) {
876 // This should only be called when we're going to return an earlier error,
877 // which would've been logged. This may imply the file is already corrupt
878 // and any further logging from FinishEntry is more likely to mislead than
879 // not.
880 this->zip_writer_->FinishEntry();
881 }
882 };
883 auto scope_guard = android::base::make_scope_guard(finish_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -0800884 auto start = std::chrono::steady_clock::now();
885 auto end = start + timeout;
886 struct pollfd pfd = {fd, POLLIN};
Felipe Lemee82a27d2016-01-05 13:35:44 -0800887
Felipe Leme770410d2016-01-26 17:07:14 -0800888 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800889 while (1) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800890 if (timeout.count() > 0) {
891 // lambda to recalculate the timeout.
892 auto time_left_ms = [end]() {
893 auto now = std::chrono::steady_clock::now();
894 auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
895 return std::max(diff.count(), 0LL);
896 };
897
898 int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
899 if (rc < 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000900 MYLOGE("Error in poll while adding from fd to zip entry %s:%s\n",
901 entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800902 return -errno;
903 } else if (rc == 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000904 MYLOGE("Timed out adding from fd to zip entry %s:%s Timeout:%lldms\n",
Vishnu Naire97d6122018-01-18 13:58:56 -0800905 entry_name.c_str(), strerror(errno), timeout.count());
906 return TIMED_OUT;
907 }
908 }
909
Zach Riggle22200402016-08-18 01:01:24 -0400910 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800911 if (bytes_read == 0) {
912 break;
913 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800914 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800915 return -errno;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800916 }
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700917 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800918 if (err) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700919 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800920 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800921 }
922 }
923
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700924 err = zip_writer_->FinishEntry();
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000925 finished_entry = true;
Felipe Leme1d486fe2016-10-14 18:06:47 -0700926 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700927 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800928 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800929 }
930
Vishnu Naire97d6122018-01-18 13:58:56 -0800931 return OK;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800932}
933
Felipe Leme1d486fe2016-10-14 18:06:47 -0700934bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
935 android::base::unique_fd fd(
936 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700937 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800938 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800939 return false;
940 }
941
Vishnu Naire97d6122018-01-18 13:58:56 -0800942 return (AddZipEntryFromFd(entry_name, fd.get()) == OK);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800943}
944
945/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700946static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800947 return (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) == OK) ? 0 : 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800948}
949
Felipe Leme1d486fe2016-10-14 18:06:47 -0700950void Dumpstate::AddDir(const std::string& dir, bool recursive) {
Felipe Leme678727a2016-09-21 17:22:11 -0700951 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
Felipe Leme46b85da2016-11-21 17:40:45 -0800952 DurationReporter duration_reporter(dir, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700953 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800954}
955
Felipe Leme1d486fe2016-10-14 18:06:47 -0700956bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800957 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Kevin Jeon9bbe0ac2022-05-05 22:05:43 +0000958 size_t flags = ZipWriter::kCompress | ZipWriter::kDefaultCompression;
959 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), flags, ds.now_);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700960 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700961 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700962 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800963 return false;
964 }
965
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700966 err = zip_writer_->WriteBytes(content.c_str(), content.length());
Felipe Leme1d486fe2016-10-14 18:06:47 -0700967 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700968 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700969 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800970 return false;
971 }
972
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700973 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700974 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700975 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800976 return false;
977 }
978
979 return true;
980}
981
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800982static void DoKmsg() {
983 struct stat st;
984 if (!stat(PSTORE_LAST_KMSG, &st)) {
985 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
986 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
987 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
988 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
989 } else {
990 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
991 DumpFile("LAST KMSG", "/proc/last_kmsg");
992 }
993}
994
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800995static void DoKernelLogcat() {
Yao Chenbe3bbc12018-01-17 16:31:10 -0800996 unsigned long timeout_ms = logcat_timeout({"kernel"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800997 RunCommand(
998 "KERNEL LOG",
999 {"logcat", "-b", "kernel", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1000 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1001}
1002
Nandana Duttdb379fa2019-10-09 16:54:41 +01001003static void DoSystemLogcat(time_t since) {
1004 char since_str[80];
1005 strftime(since_str, sizeof(since_str), "%Y-%m-%d %H:%M:%S.000", localtime(&since));
1006
1007 unsigned long timeout_ms = logcat_timeout({"main", "system", "crash"});
1008 RunCommand("SYSTEM LOG",
1009 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v", "-T",
1010 since_str},
1011 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1012}
1013
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001014static void DoRadioLogcat() {
1015 unsigned long timeout_ms = logcat_timeout({"radio"});
1016 RunCommand(
1017 "RADIO LOG",
1018 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1019 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
1020}
1021
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001022static void DoLogcat() {
Vishnu Nair6921f802017-11-22 09:17:23 -08001023 unsigned long timeout_ms;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001024 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
1025 // calculate timeout
Yao Chenbe3bbc12018-01-17 16:31:10 -08001026 timeout_ms = logcat_timeout({"main", "system", "crash"});
Tony Makae737652017-03-30 17:47:09 +01001027 RunCommand("SYSTEM LOG",
Vishnu Nair6921f802017-11-22 09:17:23 -08001028 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1029 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -08001030 timeout_ms = logcat_timeout({"events"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001031 RunCommand(
1032 "EVENT LOG",
1033 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001034 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Yao Chenbe3bbc12018-01-17 16:31:10 -08001035 timeout_ms = logcat_timeout({"stats"});
1036 RunCommand(
1037 "STATS LOG",
1038 {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001039 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001040 DoRadioLogcat();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001041
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001042 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001043 RunCommand("LAST LOGCAT", {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable",
1044 "-v", "uid", "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001045}
1046
Mike Ma5c267872019-08-21 11:31:34 -07001047static void DumpIncidentReport() {
Mike Ma5c267872019-08-21 11:31:34 -07001048 const std::string path = ds.bugreport_internal_dir_ + "/tmp_incident_report";
1049 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1050 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1051 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1052 if (fd < 0) {
1053 MYLOGE("Could not open %s to dump incident report.\n", path.c_str());
1054 return;
1055 }
Kevin Jeonfa64e642023-07-27 11:36:41 -04001056 RunCommandToFd(fd, "", {"incident", "-u"},
1057 CommandOptions::WithTimeout(PropertiesHelper::IsStrictRun() ? 20 : 120).Build());
Mike Ma5c267872019-08-21 11:31:34 -07001058 bool empty = 0 == lseek(fd, 0, SEEK_END);
1059 if (!empty) {
1060 // Use a different name from "incident.proto"
1061 // /proto/incident.proto is reserved for incident service dump
1062 // i.e. metadata for debugging.
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001063 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "incident_report" + kProtoExt,
1064 path);
1065 } else {
1066 unlink(path.c_str());
Mike Ma5c267872019-08-21 11:31:34 -07001067 }
Mike Ma5c267872019-08-21 11:31:34 -07001068}
1069
Aaron Huanga99452a2022-04-27 18:51:16 +08001070static void DumpNetstatsProto() {
1071 const std::string path = ds.bugreport_internal_dir_ + "/tmp_netstats_proto";
1072 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1073 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1074 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1075 if (fd < 0) {
1076 MYLOGE("Could not open %s to dump netstats proto.\n", path.c_str());
1077 return;
1078 }
1079 RunCommandToFd(fd, "", {"dumpsys", "netstats", "--proto"},
Kevin Jeon2fb3dd62022-09-28 18:48:55 +00001080 CommandOptions::WithTimeout(5).Build());
Aaron Huanga99452a2022-04-27 18:51:16 +08001081 bool empty = 0 == lseek(fd, 0, SEEK_END);
1082 if (!empty) {
1083 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "netstats" + kProtoExt,
1084 path);
1085 } else {
1086 unlink(path.c_str());
1087 }
1088}
1089
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001090static void MaybeAddSystemTraceToZip() {
1091 // This function copies into the .zip the system trace that was snapshotted
Kean Mariottica20f2d2023-12-15 09:34:25 +00001092 // by the early call to MaybeSnapshotSystemTraceAsync(), if any background
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001093 // tracing was happening.
Kean Mariotti853b73a2023-07-27 12:40:30 +00001094 bool system_trace_exists = access(SYSTEM_TRACE_SNAPSHOT, F_OK) == 0;
1095 if (!system_trace_exists) {
Kean Mariottica20f2d2023-12-15 09:34:25 +00001096 // No background trace was happening at the time MaybeSnapshotSystemTraceAsync() was invoked
Kean Mariotti853b73a2023-07-27 12:40:30 +00001097 if (!PropertiesHelper::IsUserBuild()) {
1098 MYLOGI(
1099 "No system traces found. Check for previously uploaded traces by looking for "
1100 "go/trace-uuid in logcat")
1101 }
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001102 return;
1103 }
1104 ds.AddZipEntry(
1105 ZIP_ROOT_DIR + SYSTEM_TRACE_SNAPSHOT,
1106 SYSTEM_TRACE_SNAPSHOT);
1107 android::os::UnlinkAndLogOnError(SYSTEM_TRACE_SNAPSHOT);
1108}
1109
Sunny Goyal35949782019-11-19 15:54:36 -08001110static void DumpVisibleWindowViews() {
Sunny Goyal35949782019-11-19 15:54:36 -08001111 DurationReporter duration_reporter("VISIBLE WINDOW VIEWS");
1112 const std::string path = ds.bugreport_internal_dir_ + "/tmp_visible_window_views";
1113 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1114 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1115 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1116 if (fd < 0) {
1117 MYLOGE("Could not open %s to dump visible views.\n", path.c_str());
1118 return;
1119 }
1120 RunCommandToFd(fd, "", {"cmd", "window", "dump-visible-window-views"},
Kevin Jeon774abde2022-09-28 18:20:43 +00001121 CommandOptions::WithTimeout(10).Build());
Sunny Goyal35949782019-11-19 15:54:36 -08001122 bool empty = 0 == lseek(fd, 0, SEEK_END);
1123 if (!empty) {
1124 ds.AddZipEntry("visible_windows.zip", path);
1125 } else {
1126 MYLOGW("Failed to dump visible windows\n");
1127 }
1128 unlink(path.c_str());
1129}
1130
Jayachandran Ca94c7172017-06-10 15:08:12 -07001131static void DumpIpTablesAsRoot() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001132 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
1133 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +09001134 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001135 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +09001136 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
1137 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
1138 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
1139 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001140}
1141
Woody Lin20767a92022-11-29 15:50:24 +08001142static void DumpShutdownCheckpoints() {
1143 const bool shutdown_checkpoints_dumped = AddDumps(
1144 ds.shutdown_checkpoints_.begin(), ds.shutdown_checkpoints_.end(),
1145 "SHUTDOWN CHECKPOINTS", false /* add_to_zip */);
1146 if (!shutdown_checkpoints_dumped) {
1147 printf("*** NO SHUTDOWN CHECKPOINTS to dump in %s\n\n",
1148 SHUTDOWN_CHECKPOINTS_DIR.c_str());
1149 }
1150}
1151
David Andersond9ba4752018-12-11 18:26:59 -08001152static void DumpDynamicPartitionInfo() {
1153 if (!::android::base::GetBoolProperty("ro.boot.dynamic_partitions", false)) {
1154 return;
1155 }
1156
1157 RunCommand("LPDUMP", {"lpdump", "--all"});
David Anderson6650ade2019-10-02 15:18:59 -07001158 RunCommand("DEVICE-MAPPER", {"gsid", "dump-device-mapper"});
David Andersond9ba4752018-12-11 18:26:59 -08001159}
1160
Chris Morin5a50d482022-02-01 17:41:18 -08001161static void AddAnrTraceDir(const std::string& anr_traces_dir) {
Narayan Kamath8f788292017-05-25 13:20:39 +01001162 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
1163 anr_traces_dir.c_str());
1164
1165 // If we're here, dump_traces_path will always be a temporary file
1166 // (created with mkostemp or similar) that contains dumps taken earlier
1167 // on in the process.
1168 if (dump_traces_path != nullptr) {
Chris Morin5a50d482022-02-01 17:41:18 -08001169 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
1170 dump_traces_path);
1171 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
Narayan Kamath8f788292017-05-25 13:20:39 +01001172
1173 const int ret = unlink(dump_traces_path);
1174 if (ret == -1) {
1175 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
1176 strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -07001177 }
1178 }
1179
Narayan Kamathbd863722017-06-01 18:50:12 +01001180 // Add a specific message for the first ANR Dump.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001181 if (ds.anr_data_.size() > 0) {
Chris Morin5a50d482022-02-01 17:41:18 -08001182 // The "last" ANR will always be present in the body of the main entry.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001183 AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1,
Chris Morin5a50d482022-02-01 17:41:18 -08001184 "VM TRACES AT LAST ANR", false /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001185
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001186 // Historical ANRs are always included as separate entries in the bugreport zip file.
Chris Morin5a50d482022-02-01 17:41:18 -08001187 AddDumps(ds.anr_data_.begin(), ds.anr_data_.end(),
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001188 "HISTORICAL ANR", true /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001189 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +01001190 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
1191 }
Andy Hungd62f7e62024-01-11 15:47:52 -08001192
1193 // Add Java anr traces (such as generated by the Finalizer Watchdog).
1194 AddDumps(ds.anr_trace_data_.begin(), ds.anr_trace_data_.end(), "JAVA ANR TRACES",
1195 true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001196}
1197
1198static void AddAnrTraceFiles() {
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001199 std::string anr_traces_dir = "/data/anr";
Narayan Kamath8f788292017-05-25 13:20:39 +01001200
Chris Morin5a50d482022-02-01 17:41:18 -08001201 AddAnrTraceDir(anr_traces_dir);
Narayan Kamath8f788292017-05-25 13:20:39 +01001202
Makoto Onuki83ec63f2019-01-31 17:08:59 -08001203 RunCommand("ANR FILES", {"ls", "-lt", ANR_DIR});
1204
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001205 // Slow traces for slow operations.
Felipe Lemee184f662016-10-27 10:04:47 -07001206 struct stat st;
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001207 int i = 0;
1208 while (true) {
1209 const std::string slow_trace_path =
1210 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
1211 if (stat(slow_trace_path.c_str(), &st)) {
1212 // No traces file at this index, done with the files.
1213 break;
Felipe Lemee184f662016-10-27 10:04:47 -07001214 }
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001215 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
1216 i++;
Felipe Lemee184f662016-10-27 10:04:47 -07001217 }
1218}
1219
Wei Wang509bb5d2017-06-09 14:42:12 -07001220static void DumpBlockStatFiles() {
1221 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -07001222
Wei Wang1dc1ef52017-06-12 11:28:37 -07001223 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
1224
1225 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001226 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1227 return;
1228 }
1229
1230 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -07001231 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001232 if ((d->d_name[0] == '.')
1233 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1234 || (d->d_name[1] == '\0'))) {
1235 continue;
1236 }
1237 const std::string new_path =
1238 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1239 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1240 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1241 printf("\n");
1242 }
Wei Wang1dc1ef52017-06-12 11:28:37 -07001243 return;
Wei Wang509bb5d2017-06-09 14:42:12 -07001244}
Jayachandran Ca94c7172017-06-10 15:08:12 -07001245
1246static void DumpPacketStats() {
1247 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
Jayachandran Ca94c7172017-06-10 15:08:12 -07001248}
1249
1250static void DumpIpAddrAndRules() {
1251 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
Ray Chencbf278a2023-11-20 07:49:45 +00001252 RunCommand("NETWORK INTERFACES", {"ip", "-s", "link"});
Jayachandran Ca94c7172017-06-10 15:08:12 -07001253 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1254 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1255 RunCommand("IP RULES", {"ip", "rule", "show"});
1256 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1257}
1258
Nandana Dutt5c390032019-03-12 10:52:56 +00001259static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, int priority,
1260 std::chrono::milliseconds timeout,
1261 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001262 auto start = std::chrono::steady_clock::now();
Vishnu Naire97d6122018-01-18 13:58:56 -08001263 sp<android::IServiceManager> sm = defaultServiceManager();
1264 Dumpsys dumpsys(sm.get());
Vishnu Naire97d6122018-01-18 13:58:56 -08001265 Vector<String16> args;
1266 Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
Vishnu Naire97d6122018-01-18 13:58:56 -08001267 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1268 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001269 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001270 std::string path(title);
1271 path.append(" - ").append(String8(service).c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -08001272 size_t bytes_written = 0;
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001273 if (PropertiesHelper::IsDryRun()) {
1274 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1275 dumpsys.writeDumpFooter(STDOUT_FILENO, service, std::chrono::milliseconds(1));
1276 } else {
Devin Mooref492c1a2023-03-15 19:19:03 +00001277 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP | Dumpsys::TYPE_PID |
1278 Dumpsys::TYPE_CLIENTS | Dumpsys::TYPE_THREAD,
Devin Mooreae68df22023-02-24 20:59:51 +00001279 service, args);
1280 if (status == OK) {
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001281 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1282 std::chrono::duration<double> elapsed_seconds;
1283 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH &&
1284 service == String16("meminfo")) {
1285 // Use a longer timeout for meminfo, since 30s is not always enough.
1286 status = dumpsys.writeDump(STDOUT_FILENO, service, 60s,
1287 /* as_proto = */ false, elapsed_seconds,
1288 bytes_written);
1289 } else {
1290 status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
1291 /* as_proto = */ false, elapsed_seconds,
1292 bytes_written);
1293 }
1294 dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
1295 bool dump_complete = (status == OK);
1296 dumpsys.stopDumpThread(dump_complete);
Devin Moorecdfa4602023-03-16 20:49:39 +00001297 } else {
1298 MYLOGE("Failed to start dump thread for service: %s, status: %d",
1299 String8(service).c_str(), status);
Gavin Corkeryfac7e2b2021-07-08 22:39:02 +01001300 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001301 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001302
1303 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1304 std::chrono::steady_clock::now() - start);
1305 if (elapsed_duration > timeout) {
1306 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1307 elapsed_duration.count());
1308 break;
1309 }
1310 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001311 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001312}
1313
Vishnu Nair64afc022018-02-01 15:29:34 -08001314static void RunDumpsysText(const std::string& title, int priority,
1315 std::chrono::milliseconds timeout,
1316 std::chrono::milliseconds service_timeout) {
1317 DurationReporter duration_reporter(title);
1318 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1319 fsync(STDOUT_FILENO);
1320 RunDumpsysTextByPriority(title, priority, timeout, service_timeout);
1321}
1322
1323/* Dump all services registered with Normal or Default priority. */
Nandana Dutt5c390032019-03-12 10:52:56 +00001324static Dumpstate::RunStatus RunDumpsysTextNormalPriority(const std::string& title,
1325 std::chrono::milliseconds timeout,
1326 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001327 DurationReporter duration_reporter(title);
1328 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1329 fsync(STDOUT_FILENO);
1330 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout,
1331 service_timeout);
Nandana Dutt5c390032019-03-12 10:52:56 +00001332
1333 RETURN_IF_USER_DENIED_CONSENT();
1334
1335 return RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1336 service_timeout);
Vishnu Nair64afc022018-02-01 15:29:34 -08001337}
1338
Nandana Dutt5c390032019-03-12 10:52:56 +00001339static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priority,
1340 std::chrono::milliseconds timeout,
1341 std::chrono::milliseconds service_timeout) {
Vishnu Naire97d6122018-01-18 13:58:56 -08001342 sp<android::IServiceManager> sm = defaultServiceManager();
1343 Dumpsys dumpsys(sm.get());
1344 Vector<String16> args;
1345 Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
1346 DurationReporter duration_reporter(title);
1347
1348 auto start = std::chrono::steady_clock::now();
1349 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
1350 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001351 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001352 std::string path(kProtoPath);
1353 path.append(String8(service).c_str());
1354 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
1355 path.append("_CRITICAL");
1356 } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
1357 path.append("_HIGH");
1358 }
1359 path.append(kProtoExt);
Steven Morelandcbd69fc2021-07-20 20:45:43 +00001360 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP, service, args);
Vishnu Naire97d6122018-01-18 13:58:56 -08001361 if (status == OK) {
1362 status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
1363 bool dumpTerminated = (status == OK);
1364 dumpsys.stopDumpThread(dumpTerminated);
1365 }
1366 ZipWriter::FileEntry file_entry;
1367 ds.zip_writer_->GetLastEntry(&file_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -08001368
1369 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1370 std::chrono::steady_clock::now() - start);
1371 if (elapsed_duration > timeout) {
1372 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1373 elapsed_duration.count());
1374 break;
1375 }
1376 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001377 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001378}
1379
Nandana Dutta7db6342018-11-21 14:53:34 +00001380// Runs dumpsys on services that must dump first and will take less than 100ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001381static Dumpstate::RunStatus RunDumpsysCritical() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001382 RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1383 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Nandana Dutt5c390032019-03-12 10:52:56 +00001384
1385 RETURN_IF_USER_DENIED_CONSENT();
1386
1387 return RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1388 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Vishnu Nair780b1282017-10-10 13:57:24 -07001389}
1390
1391// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001392static Dumpstate::RunStatus RunDumpsysHigh() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001393 // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
1394 // high priority. Reduce timeout once they are able to dump in a shorter time or
1395 // moved to a parallel task.
1396 RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1397 /* timeout= */ 90s, /* service_timeout= */ 30s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001398
1399 RETURN_IF_USER_DENIED_CONSENT();
1400
1401 return RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1402 /* timeout= */ 5s, /* service_timeout= */ 1s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001403}
1404
1405// Runs dumpsys on services that must dump but can take up to 10s to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001406static Dumpstate::RunStatus RunDumpsysNormal() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001407 RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001408
1409 RETURN_IF_USER_DENIED_CONSENT();
1410
1411 return RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1412 /* timeout= */ 90s, /* service_timeout= */ 10s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001413}
1414
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001415/*
1416 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1417 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1418 * if it's not running in the parallel task.
1419 */
1420static void DumpHals(int out_fd = STDOUT_FILENO) {
Yifan Hong30528a22020-08-07 18:24:06 -07001421 RunCommand("HARDWARE HALS", {"lshal", "--all", "--types=all"},
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001422 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build(),
1423 false, out_fd);
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001424
Steven Moreland44cd9482018-01-04 16:24:13 -08001425 using android::hidl::manager::V1_0::IServiceManager;
1426 using android::hardware::defaultServiceManager;
1427
1428 sp<IServiceManager> sm = defaultServiceManager();
1429 if (sm == nullptr) {
1430 MYLOGE("Could not retrieve hwservicemanager to dump hals.\n");
1431 return;
1432 }
1433
1434 auto ret = sm->list([&](const auto& interfaces) {
1435 for (const std::string& interface : interfaces) {
1436 std::string cleanName = interface;
Steven Morelandc6b1fc22023-07-26 23:53:58 +00001437 std::replace_if(
1438 cleanName.begin(), cleanName.end(),
1439 [](char c) {
1440 return !isalnum(c) && std::string("@-_.").find(c) == std::string::npos;
1441 },
1442 '_');
Nandana Dutt979388e2018-11-30 16:48:55 +00001443 const std::string path = ds.bugreport_internal_dir_ + "/lshal_debug_" + cleanName;
Steven Moreland44cd9482018-01-04 16:24:13 -08001444
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001445 bool empty = false;
Steven Moreland44cd9482018-01-04 16:24:13 -08001446 {
1447 auto fd = android::base::unique_fd(
1448 TEMP_FAILURE_RETRY(open(path.c_str(),
1449 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1450 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1451 if (fd < 0) {
1452 MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str());
1453 continue;
1454 }
1455 RunCommandToFd(fd,
1456 "",
Steven Morelandc81cd3c2018-01-18 14:36:26 -08001457 {"lshal", "debug", "-E", interface},
Steven Moreland44cd9482018-01-04 16:24:13 -08001458 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1459
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001460 empty = 0 == lseek(fd, 0, SEEK_END);
Steven Moreland44cd9482018-01-04 16:24:13 -08001461 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001462 if (!empty) {
1463 ds.EnqueueAddZipEntryAndCleanupIfNeeded("lshal-debug/" + cleanName + ".txt",
1464 path);
1465 } else {
1466 unlink(path.c_str());
1467 }
Steven Moreland44cd9482018-01-04 16:24:13 -08001468 }
1469 });
1470
1471 if (!ret.isOk()) {
1472 MYLOGE("Could not list hals from hwservicemanager.\n");
1473 }
1474}
1475
Devin Moore8df81bb2022-06-08 22:47:02 +00001476// Dump all of the files that make up the vendor interface.
1477// See the files listed in dumpFileList() for the latest list of files.
1478static void DumpVintf() {
Devin Moore16271d92022-09-22 18:28:48 +00001479
1480 const std::string sku = android::base::GetProperty("ro.boot.product.hardware.sku", "");
1481 const auto vintfFiles = android::vintf::details::dumpFileList(sku);
Devin Moore8df81bb2022-06-08 22:47:02 +00001482 for (const auto vintfFile : vintfFiles) {
1483 struct stat st;
1484 if (stat(vintfFile.c_str(), &st) == 0) {
1485 if (S_ISDIR(st.st_mode)) {
1486 ds.AddDir(vintfFile, true /* recursive */);
1487 } else {
1488 ds.EnqueueAddZipEntryAndCleanupIfNeeded(ZIP_ROOT_DIR + vintfFile,
1489 vintfFile);
1490 }
1491 }
1492 }
1493}
1494
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001495static void DumpExternalFragmentationInfo() {
1496 struct stat st;
1497 if (stat("/proc/buddyinfo", &st) != 0) {
1498 MYLOGE("Unable to dump external fragmentation info\n");
1499 return;
1500 }
1501
1502 printf("------ EXTERNAL FRAGMENTATION INFO ------\n");
1503 std::ifstream ifs("/proc/buddyinfo");
1504 auto unusable_index_regex = std::regex{"Node\\s+([0-9]+),\\s+zone\\s+(\\S+)\\s+(.*)"};
1505 for (std::string line; std::getline(ifs, line);) {
1506 std::smatch match_results;
1507 if (std::regex_match(line, match_results, unusable_index_regex)) {
1508 std::stringstream free_pages(std::string{match_results[3]});
1509 std::vector<int> free_pages_per_order(std::istream_iterator<int>{free_pages},
1510 std::istream_iterator<int>());
1511
1512 int total_free_pages = 0;
1513 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1514 total_free_pages += (free_pages_per_order[i] * std::pow(2, i));
1515 }
1516
1517 printf("Node %s, zone %8s", match_results[1].str().c_str(),
1518 match_results[2].str().c_str());
1519
1520 int usable_free_pages = total_free_pages;
1521 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1522 auto unusable_index = (total_free_pages - usable_free_pages) /
1523 static_cast<double>(total_free_pages);
1524 printf(" %5.3f", unusable_index);
1525 usable_free_pages -= (free_pages_per_order[i] * std::pow(2, i));
1526 }
1527
1528 printf("\n");
1529 }
1530 }
1531 printf("\n");
1532}
1533
mhasankd451a472020-05-26 18:02:39 -07001534static void DumpstateLimitedOnly() {
EdenSue8fe4522023-11-20 15:37:23 +08001535 // Trimmed-down version of dumpstate to only include a allowlisted
mhasankd451a472020-05-26 18:02:39 -07001536 // set of logs (system log, event log, and system server / system app
1537 // crashes, and networking logs). See b/136273873 and b/138459828
1538 // for context.
1539 DurationReporter duration_reporter("DUMPSTATE");
1540 unsigned long timeout_ms;
1541 // calculate timeout
1542 timeout_ms = logcat_timeout({"main", "system", "crash"});
1543 RunCommand("SYSTEM LOG",
1544 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1545 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1546 timeout_ms = logcat_timeout({"events"});
1547 RunCommand(
1548 "EVENT LOG",
1549 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1550 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1551
1552 printf("========================================================\n");
1553 printf("== Networking Service\n");
1554 printf("========================================================\n");
1555
1556 RunDumpsys("DUMPSYS NETWORK_SERVICE_LIMITED", {"wifi", "-a"},
1557 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hugo Benichiaa162682020-10-30 23:28:56 +09001558 RunDumpsys("DUMPSYS CONNECTIVITY REQUESTS", {"connectivity", "requests"},
1559 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
mhasankd451a472020-05-26 18:02:39 -07001560
1561 printf("========================================================\n");
1562 printf("== Dropbox crashes\n");
1563 printf("========================================================\n");
1564
1565 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1566 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1567
Bryan Yuefb85d92024-02-02 13:37:06 +00001568
1569 printf("========================================================\n");
1570 printf("== ANR Traces\n");
1571 printf("========================================================\n");
1572
1573 AddAnrTraceFiles();
1574
mhasankd451a472020-05-26 18:02:39 -07001575 printf("========================================================\n");
1576 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1577 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1578 printf("========================================================\n");
1579 printf("== dumpstate: done (id %d)\n", ds.id_);
1580 printf("========================================================\n");
1581}
1582
Rhed Jaoe017f982020-07-21 17:58:41 +08001583/*
1584 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1585 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1586 * if it's not running in the parallel task.
1587 */
1588static void DumpCheckins(int out_fd = STDOUT_FILENO) {
1589 dprintf(out_fd, "========================================================\n");
1590 dprintf(out_fd, "== Checkins\n");
1591 dprintf(out_fd, "========================================================\n");
1592
1593 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"}, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001594 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"}, out_fd);
1595 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"}, out_fd);
1596 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"}, out_fd);
1597 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"}, out_fd);
1598}
1599
1600/*
1601 * Runs dumpsys on activity service to dump all application activities, services
1602 * and providers in the device.
1603 *
1604 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1605 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1606 * if it's not running in the parallel task.
1607 */
1608static void DumpAppInfos(int out_fd = STDOUT_FILENO) {
1609 dprintf(out_fd, "========================================================\n");
1610 dprintf(out_fd, "== Running Application Activities\n");
1611 dprintf(out_fd, "========================================================\n");
1612
1613 // The following dumpsys internally collects output from running apps, so it can take a long
1614 // time. So let's extend the timeout.
1615
1616 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1617
1618 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1619
1620 dprintf(out_fd, "========================================================\n");
1621 dprintf(out_fd, "== Running Application Services (platform)\n");
1622 dprintf(out_fd, "========================================================\n");
1623
1624 RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
1625 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1626
1627 dprintf(out_fd, "========================================================\n");
1628 dprintf(out_fd, "== Running Application Services (non-platform)\n");
1629 dprintf(out_fd, "========================================================\n");
1630
1631 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1632 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1633
1634 dprintf(out_fd, "========================================================\n");
1635 dprintf(out_fd, "== Running Application Providers (platform)\n");
1636 dprintf(out_fd, "========================================================\n");
1637
1638 RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
Rhed Jaob049f182021-01-11 21:08:43 +08001639 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001640
1641 dprintf(out_fd, "========================================================\n");
1642 dprintf(out_fd, "== Running Application Providers (non-platform)\n");
1643 dprintf(out_fd, "========================================================\n");
1644
1645 RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1646 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1647}
1648
Nandana Dutt5c390032019-03-12 10:52:56 +00001649// Dumps various things. Returns early with status USER_CONSENT_DENIED if user denies consent
1650// via the consent they are shown. Ignores other errors that occur while running various
1651// commands. The consent checking is currently done around long running tasks, which happen to
1652// be distributed fairly evenly throughout the function.
Kean Mariotti306633e2022-09-05 16:30:47 +00001653Dumpstate::RunStatus Dumpstate::dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001654 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001655
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001656 // Enqueue slow functions into the thread pool, if the parallel run is enabled.
Aaron Huanga99452a2022-04-27 18:51:16 +08001657 std::future<std::string> dump_hals, dump_incident_report, dump_board, dump_checkins,
Kean Mariottica20f2d2023-12-15 09:34:25 +00001658 dump_netstats_report;
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001659 if (ds.dump_pool_) {
1660 // Pool was shutdown in DumpstateDefaultAfterCritical method in order to
Kean Mariotti306633e2022-09-05 16:30:47 +00001661 // drop root user. Restarts it.
1662 ds.dump_pool_->start(/* thread_counts = */3);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001663
Chris Morinbc223142022-02-04 14:17:11 -08001664 dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
1665 dump_incident_report = ds.dump_pool_->enqueueTask(
1666 DUMP_INCIDENT_REPORT_TASK, &DumpIncidentReport);
Aaron Huanga99452a2022-04-27 18:51:16 +08001667 dump_netstats_report = ds.dump_pool_->enqueueTask(
1668 DUMP_NETSTATS_PROTO_TASK, &DumpNetstatsProto);
Chris Morinbc223142022-02-04 14:17:11 -08001669 dump_board = ds.dump_pool_->enqueueTaskWithFd(
1670 DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
1671 dump_checkins = ds.dump_pool_->enqueueTaskWithFd(DUMP_CHECKINS_TASK, &DumpCheckins, _1);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001672 }
1673
Nandana Dutt5c390032019-03-12 10:52:56 +00001674 // Dump various things. Note that anything that takes "long" (i.e. several seconds) should
1675 // check intermittently (if it's intrerruptable like a foreach on pids) and/or should be wrapped
1676 // in a consent check (via RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK).
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001677 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001678 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001679 DumpBlockStatFiles();
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001680 DumpFile("MEMORY INFO", "/proc/meminfo");
1681 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001682 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001683
Kevin Jeon947922b2022-09-21 00:29:18 +00001684 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "BUGREPORT_PROCDUMP", {"bugreport_procdump"},
1685 CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001686
Sunny Goyal35949782019-11-19 15:54:36 -08001687 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpVisibleWindowViews);
1688
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001689 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1690 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1691 DumpFile("SLAB INFO", "/proc/slabinfo");
1692 DumpFile("ZONEINFO", "/proc/zoneinfo");
1693 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1694 DumpFile("BUDDYINFO", "/proc/buddyinfo");
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001695 DumpExternalFragmentationInfo();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001696
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001697 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001698
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001699 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001700 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001701
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001702 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001703 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_hals));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001704 } else {
1705 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_HALS_TASK, DumpHals);
1706 }
Steven Moreland81b429e2017-01-31 19:50:46 -08001707
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001708 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001709 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001710 struct stat s;
1711 if (stat("/proc/modules", &s) != 0) {
1712 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1713 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001714 RunCommand("LSMOD", {"lsmod"});
Woody Linc198f252021-05-04 16:37:11 +08001715 RunCommand("MODULES INFO",
1716 {"sh", "-c", "cat /proc/modules | cut -d' ' -f1 | "
1717 " while read MOD ; do echo modinfo:$MOD ; modinfo $MOD ; "
1718 "done"}, CommandOptions::AS_ROOT);
Felipe Lemee4eca582016-06-10 17:48:08 -07001719 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001720
Tom Cherryb87dbfa2020-07-28 11:28:53 -07001721 if (android::base::GetBoolProperty("ro.logd.kernel", false)) {
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001722 DoKernelLogcat();
1723 } else {
1724 do_dmesg();
1725 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001726
Devin Moore8df81bb2022-06-08 22:47:02 +00001727 DumpVintf();
1728
Felipe Lemef0292972016-11-22 13:57:05 -08001729 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001730
Jeff Brown1dc94e32014-09-11 14:15:27 -07001731 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001732 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001733
Jack Yu5a6b2e22020-08-14 18:13:35 +08001734 /* Dump Nfc NCI logs */
1735 ds.AddDir("/data/misc/nfc/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001736
Paul Chang0d2aad72020-02-13 20:04:03 +08001737 if (ds.options_->do_screenshot && !ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001738 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001739 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001740 }
1741
Felipe Lemee184f662016-10-27 10:04:47 -07001742 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001743
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001744 MaybeAddSystemTraceToZip();
1745
Narayan Kamath8f788292017-05-25 13:20:39 +01001746 // NOTE: tombstones are always added as separate entries in the zip archive
1747 // and are not interspersed with the main report.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001748 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
Narayan Kamathbd863722017-06-01 18:50:12 +01001749 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001750 if (!tombstones_dumped) {
1751 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001752 }
1753
Jayachandran Ca94c7172017-06-10 15:08:12 -07001754 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001755
Lorenzo Colitti807f2dd2022-05-27 12:48:37 +09001756 RunDumpsys("EBPF MAP STATS", {"connectivity", "trafficcontroller"});
Chenbo Feng276a3b62018-08-07 11:44:49 -07001757
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001758 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001759
Woody Lin20767a92022-11-29 15:50:24 +08001760 DumpShutdownCheckpoints();
1761
Jayachandran Ca94c7172017-06-10 15:08:12 -07001762 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001763
1764 dump_route_tables();
1765
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001766 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1767 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1768 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001769
Nandana Dutt5c390032019-03-12 10:52:56 +00001770 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysHigh);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001771
Chiachang Wang668ede42021-05-17 17:14:20 +08001772 // The dump mechanism in connectivity is refactored due to modularization work. Connectivity can
1773 // only register with a default priority(NORMAL priority). Dumpstate has to call connectivity
1774 // dump with priority parameters to dump high priority information.
1775 RunDumpsys("SERVICE HIGH connectivity", {"connectivity", "--dump-priority", "HIGH"},
1776 CommandOptions::WithTimeout(10).Build());
1777
Elliott Hughes23ccc622017-02-28 10:14:22 -08001778 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001779
Joe Onoratod38bc3a2023-06-29 15:48:28 -07001780 DumpFile("SYSTEM BUILD-TIME RELEASE FLAGS", "/system/etc/build_flags.json");
1781 DumpFile("SYSTEM_EXT BUILD-TIME RELEASE FLAGS", "/system_ext/etc/build_flags.json");
1782 DumpFile("PRODUCT BUILD-TIME RELEASE FLAGS", "/product/etc/build_flags.json");
1783 DumpFile("VENDOR BUILD-TIME RELEASE FLAGS", "/vendor/etc/build_flags.json");
1784
MÃ¥rten Kongstad5ad813f2023-09-28 10:09:18 +02001785 RunCommand("ACONFIG FLAGS", {PRINT_FLAGS},
1786 CommandOptions::WithTimeout(10).Always().DropRoot().Build());
Joe Onoratod38bc3a2023-06-29 15:48:28 -07001787
Jin Qianf334d662017-10-10 14:41:37 -07001788 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001789
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001790 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001791
Colin Crossf45fa6b2012-03-26 12:38:26 -07001792 /* Binder state is expensive to look at as it uses a lot of memory. */
Hridya Valsaraju920ba712020-02-09 16:27:01 -08001793 std::string binder_logs_dir = access("/dev/binderfs/binder_logs", R_OK) ?
1794 "/sys/kernel/debug/binder" : "/dev/binderfs/binder_logs";
1795
1796 DumpFile("BINDER FAILED TRANSACTION LOG", binder_logs_dir + "/failed_transaction_log");
1797 DumpFile("BINDER TRANSACTION LOG", binder_logs_dir + "/transaction_log");
1798 DumpFile("BINDER TRANSACTIONS", binder_logs_dir + "/transactions");
1799 DumpFile("BINDER STATS", binder_logs_dir + "/stats");
1800 DumpFile("BINDER STATE", binder_logs_dir + "/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001801
Yifan Hongd90cc652020-02-08 16:52:02 -08001802 ds.AddDir(SNAPSHOTCTL_LOG_DIR, false);
1803
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001804 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001805 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_board));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001806 } else {
1807 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
1808 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001809
Steven Moreland7440ddb2016-12-15 16:13:39 -08001810 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001811 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1812 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001813 // su does not exist on user builds, so try running without it.
1814 // This way any implementations of vril-dump that do not require
1815 // root can run on user builds.
1816 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001817 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001818 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001819 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001820 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001821 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001822 }
1823
Felipe Lemed8b94e52016-12-08 10:21:44 -08001824 printf("========================================================\n");
1825 printf("== Android Framework Services\n");
1826 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001827
Nandana Dutt5c390032019-03-12 10:52:56 +00001828 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001829
Jack He91ff2fe2021-02-18 18:23:43 -08001830 /* Dump Bluetooth HCI logs after getting bluetooth_manager dumpsys */
1831 ds.AddDir("/data/misc/bluetooth/logs", true);
1832
Rhed Jaoe017f982020-07-21 17:58:41 +08001833 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001834 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_checkins));
Rhed Jaoe017f982020-07-21 17:58:41 +08001835 } else {
1836 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_CHECKINS_TASK, DumpCheckins);
1837 }
Dianne Hackborn02bea972013-06-26 18:59:09 -07001838
Rhed Jaoc5f7ec32020-12-22 22:11:08 +08001839 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpAppInfos);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001840
Adrian Roos8b397ab2017-04-04 16:35:44 -07001841 printf("========================================================\n");
1842 printf("== Dropbox crashes\n");
1843 printf("========================================================\n");
1844
1845 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1846 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1847
Felipe Lemed8b94e52016-12-08 10:21:44 -08001848 printf("========================================================\n");
1849 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1850 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1851 printf("========================================================\n");
1852 printf("== dumpstate: done (id %d)\n", ds.id_);
1853 printf("========================================================\n");
Bookatz38472142018-09-28 10:20:24 -07001854
1855 printf("========================================================\n");
1856 printf("== Obtaining statsd metadata\n");
1857 printf("========================================================\n");
1858 // This differs from the usual dumpsys stats, which is the stats report data.
1859 RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
Mike Ma5c267872019-08-21 11:31:34 -07001860
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +09001861 // Add linker configuration directory
1862 ds.AddDir(LINKERCONFIG_DIR, true);
1863
Li Li830179f2022-01-04 12:53:29 -08001864 /* Dump frozen cgroupfs */
1865 dump_frozen_cgroupfs();
Li Li2eedd412021-06-30 15:11:53 -07001866
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001867 if (ds.dump_pool_) {
Aaron Huanga99452a2022-04-27 18:51:16 +08001868 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_netstats_report));
1869 } else {
1870 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_NETSTATS_PROTO_TASK,
1871 DumpNetstatsProto);
1872 }
1873
1874 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001875 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_incident_report));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001876 } else {
1877 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_INCIDENT_REPORT_TASK,
1878 DumpIncidentReport);
1879 }
Mike Ma5c267872019-08-21 11:31:34 -07001880
Kean Mariotti306633e2022-09-05 16:30:47 +00001881 MaybeAddUiTracesToZip();
1882
Nandana Dutt5c390032019-03-12 10:52:56 +00001883 return Dumpstate::RunStatus::OK;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001884}
1885
Nandana Dutt5c390032019-03-12 10:52:56 +00001886/*
1887 * Dumps state for the default case; drops root after it's no longer necessary.
1888 *
1889 * Returns RunStatus::OK if everything went fine.
1890 * Returns RunStatus::ERROR if there was an error.
1891 * Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport
1892 * with the caller.
1893 */
Jichao Lie89d9c12019-11-21 19:02:51 -08001894Dumpstate::RunStatus Dumpstate::DumpstateDefaultAfterCritical() {
Nandana Duttdb379fa2019-10-09 16:54:41 +01001895 // Capture first logcat early on; useful to take a snapshot before dumpstate logs take over the
1896 // buffer.
1897 DoLogcat();
1898 // Capture timestamp after first logcat to use in next logcat
1899 time_t logcat_ts = time(nullptr);
1900
Nandana Dutt4be45d12018-09-26 15:04:23 +01001901 /* collect stack traces from Dalvik and native processes (needs root) */
Chris Morinbc223142022-02-04 14:17:11 -08001902 std::future<std::string> dump_traces;
Rhed Jao5377d792020-07-16 17:37:39 +08001903 if (dump_pool_) {
1904 RETURN_IF_USER_DENIED_CONSENT();
1905 // One thread is enough since we only need to enqueue DumpTraces here.
1906 dump_pool_->start(/* thread_counts = */1);
1907
1908 // DumpTraces takes long time, post it to the another thread in the
1909 // pool, if pool is available
Chris Morinbc223142022-02-04 14:17:11 -08001910 dump_traces = dump_pool_->enqueueTask(
1911 DUMP_TRACES_TASK, &Dumpstate::DumpTraces, &ds, &dump_traces_path);
Rhed Jao5377d792020-07-16 17:37:39 +08001912 } else {
1913 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_TRACES_TASK, ds.DumpTraces,
1914 &dump_traces_path);
1915 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001916
1917 /* Run some operations that require root. */
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001918 if (!PropertiesHelper::IsDryRun()) {
Chris Morinc2cba7a2022-02-01 17:06:50 -08001919 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX);
1920 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX);
Andy Hungd62f7e62024-01-11 15:47:52 -08001921 ds.anr_trace_data_ = GetDumpFds(ANR_DIR, ANR_TRACE_FILE_PREFIX);
Woody Lin20767a92022-11-29 15:50:24 +08001922 ds.shutdown_checkpoints_ = GetDumpFds(
1923 SHUTDOWN_CHECKPOINTS_DIR, SHUTDOWN_CHECKPOINTS_FILE_PREFIX);
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001924 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001925
1926 ds.AddDir(RECOVERY_DIR, true);
1927 ds.AddDir(RECOVERY_DATA_DIR, true);
1928 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
Kelvin Zhang6eaa0f92022-09-12 09:29:19 -07001929 ds.AddDir(UPDATE_ENGINE_PREF_DIR, true);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001930 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1931 if (!PropertiesHelper::IsUserBuild()) {
1932 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1933 ds.AddDir(PROFILE_DATA_DIR_REF, true);
Calin Juravlef84d3692020-04-28 15:31:12 -07001934 ds.AddZipEntry(ZIP_ROOT_DIR + PACKAGE_DEX_USE_LIST, PACKAGE_DEX_USE_LIST);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001935 }
Jerry Changa1df8a92020-01-02 16:03:39 +08001936 ds.AddDir(PREREBOOT_DATA_DIR, false);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001937 add_mountinfo();
Peter Collingbourne78aa2942023-02-15 14:50:31 -08001938 for (const char* path : {"/proc/cpuinfo", "/proc/meminfo"}) {
1939 ds.AddZipEntry(ZIP_ROOT_DIR + path, path);
1940 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001941 DumpIpTablesAsRoot();
David Andersond9ba4752018-12-11 18:26:59 -08001942 DumpDynamicPartitionInfo();
Yifan Hong3945e1b2019-10-29 12:59:23 -07001943 ds.AddDir(OTA_METADATA_DIR, true);
Jeff Sharkey9df29d52023-02-06 14:26:30 -07001944 if (!PropertiesHelper::IsUserBuild()) {
1945 // Include dropbox entry files inside ZIP, but exclude
1946 // noisy WTF and StrictMode entries
1947 dump_files("", DROPBOX_DIR, skip_wtf_strictmode, _add_file_from_fd);
1948 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001949
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001950 // Capture any IPSec policies in play. No keys are exposed here.
Nandana Dutt4be45d12018-09-26 15:04:23 +01001951 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1952
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001953 // Dump IPsec stats. No keys are exposed here.
1954 DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
1955
Nandana Dutt4be45d12018-09-26 15:04:23 +01001956 // Run ss as root so we can see socket marks.
1957 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1958
1959 // Run iotop as root to show top 100 IO threads
1960 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1961
Erick Reyese68df822019-02-11 14:46:36 -08001962 // Gather shared memory buffer info if the product implements it
Hridya Valsaraju1da80c52021-01-09 22:10:11 -08001963 RunCommand("Dmabuf dump", {"dmabuf_dump"});
1964 RunCommand("Dmabuf per-buffer/per-exporter/per-device stats", {"dmabuf_dump", "-b"});
Erick Reyese68df822019-02-11 14:46:36 -08001965
Minchan Kim22c6a1e2019-09-30 15:58:10 -07001966 DumpFile("PSI cpu", "/proc/pressure/cpu");
1967 DumpFile("PSI memory", "/proc/pressure/memory");
1968 DumpFile("PSI io", "/proc/pressure/io");
1969
Steven Moreland9379c462023-12-21 02:04:27 +00001970 ds.AddZipEntry(ZIP_ROOT_DIR + KERNEL_CONFIG, KERNEL_CONFIG);
1971
MÃ¥rten Kongstad60195a72022-09-20 14:14:20 +02001972 RunCommand("SDK EXTENSIONS", {SDK_EXT_INFO, "--dump"},
1973 CommandOptions::WithTimeout(10).Always().DropRoot().Build());
1974
Nattharat Jariyanuntanaetb250cae2024-05-15 07:48:19 +00001975 // Dump UWB UCI logs here because apexdata requires root access
1976 ds.AddDir(UWB_LOG_DIR, true);
1977
Rhed Jao5377d792020-07-16 17:37:39 +08001978 if (dump_pool_) {
1979 RETURN_IF_USER_DENIED_CONSENT();
Chris Morinbc223142022-02-04 14:17:11 -08001980 WaitForTask(std::move(dump_traces));
Rhed Jao5377d792020-07-16 17:37:39 +08001981
Chris Morinbc223142022-02-04 14:17:11 -08001982 // Current running thread in the pool is the root user also. Delete
1983 // the pool and make a new one later to ensure none of threads in the pool are root.
1984 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao5377d792020-07-16 17:37:39 +08001985 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001986 if (!DropRootUser()) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001987 return Dumpstate::RunStatus::ERROR;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001988 }
1989
Nandana Dutt5c390032019-03-12 10:52:56 +00001990 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttdb379fa2019-10-09 16:54:41 +01001991 Dumpstate::RunStatus status = dumpstate();
1992 // Capture logcat since the last time we did it.
1993 DoSystemLogcat(logcat_ts);
1994 return status;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001995}
1996
Rhed Jaob5685b32020-08-14 17:19:17 +08001997// Common states for telephony and wifi which are needed to be collected before
1998// dumpstate drop the root user.
1999static void DumpstateRadioAsRoot() {
2000 DumpIpTablesAsRoot();
2001 ds.AddDir(LOGPERSIST_DATA_DIR, false);
2002}
2003
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002004// This method collects common dumpsys for telephony and wifi. Typically, wifi
2005// reports are fine to include all information, but telephony reports on user
2006// builds need to strip some content (see DumpstateTelephonyOnly).
2007static void DumpstateRadioCommon(bool include_sensitive_info = true) {
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002008 // We need to be picky about some stuff for telephony reports on user builds.
2009 if (!include_sensitive_info) {
2010 // Only dump the radio log buffer (other buffers and dumps contain too much unrelated info).
2011 DoRadioLogcat();
2012 } else {
Rhed Jaob5685b32020-08-14 17:19:17 +08002013 // DumpHals takes long time, post it to the another thread in the pool,
2014 // if pool is available.
Chris Morinbc223142022-02-04 14:17:11 -08002015 std::future<std::string> dump_hals;
Rhed Jaob5685b32020-08-14 17:19:17 +08002016 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002017 dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
Rhed Jaob5685b32020-08-14 17:19:17 +08002018 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002019 // Contains various system properties and process startup info.
2020 do_dmesg();
2021 // Logs other than the radio buffer may contain package/component names and potential PII.
2022 DoLogcat();
2023 // Too broad for connectivity problems.
2024 DoKmsg();
Rhed Jaob5685b32020-08-14 17:19:17 +08002025 // DumpHals contains unrelated hardware info (camera, NFC, biometrics, ...).
2026 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002027 WaitForTask(std::move(dump_hals));
Rhed Jaob5685b32020-08-14 17:19:17 +08002028 } else {
2029 RUN_SLOW_FUNCTION_AND_LOG(DUMP_HALS_TASK, DumpHals);
2030 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002031 }
2032
Jayachandran Ca94c7172017-06-10 15:08:12 -07002033 DumpPacketStats();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002034 DumpIpAddrAndRules();
2035 dump_route_tables();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002036 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
2037 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08002038}
2039
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002040// We use "telephony" here for legacy reasons, though this now really means "connectivity" (cellular
2041// + wifi + networking). This method collects dumpsys for connectivity debugging only. General rules
2042// for what can be included on user builds: all reported information MUST directly relate to
2043// connectivity debugging or customer support and MUST NOT contain unrelated personally identifiable
2044// information. This information MUST NOT identify user-installed packages (UIDs are OK, package
2045// names are not), and MUST NOT contain logs of user application traffic.
2046// TODO(b/148168577) rename this and other related fields/methods to "connectivity" instead.
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08002047static void DumpstateTelephonyOnly(const std::string& calling_package) {
mukesh agrawal253dad42018-01-23 21:59:59 -08002048 DurationReporter duration_reporter("DUMPSTATE");
Jichao Lie89d9c12019-11-21 19:02:51 -08002049
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002050 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
mukesh agrawal253dad42018-01-23 21:59:59 -08002051
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002052 const bool include_sensitive_info = !PropertiesHelper::IsUserBuild();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002053
Rhed Jaob5685b32020-08-14 17:19:17 +08002054 DumpstateRadioAsRoot();
2055 if (!DropRootUser()) {
2056 return;
2057 }
2058
2059 // Starts thread pool after the root user is dropped, and two additional threads
2060 // are created for DumpHals in the DumpstateRadioCommon and DumpstateBoard.
Chris Morinbc223142022-02-04 14:17:11 -08002061 std::future<std::string> dump_board;
Rhed Jaob5685b32020-08-14 17:19:17 +08002062 if (ds.dump_pool_) {
2063 ds.dump_pool_->start(/*thread_counts =*/2);
2064
2065 // DumpstateBoard takes long time, post it to the another thread in the pool,
2066 // if pool is available.
Chris Morinbc223142022-02-04 14:17:11 -08002067 dump_board = ds.dump_pool_->enqueueTaskWithFd(
2068 DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
Rhed Jaob5685b32020-08-14 17:19:17 +08002069 }
2070
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002071 DumpstateRadioCommon(include_sensitive_info);
2072
2073 if (include_sensitive_info) {
2074 // Contains too much unrelated PII, and given the unstructured nature of sysprops, we can't
2075 // really cherrypick all of the connectivity-related ones. Apps generally have no business
2076 // reading these anyway, and there should be APIs to supply the info in a more app-friendly
2077 // way.
2078 RunCommand("SYSTEM PROPERTIES", {"getprop"});
2079 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002080
2081 printf("========================================================\n");
2082 printf("== Android Framework Services\n");
2083 printf("========================================================\n");
2084
Vishnu Nair652cc802017-11-30 15:18:30 -08002085 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2086 SEC_TO_MSEC(10));
Hunter Knepshield31cbae12021-05-11 16:23:24 -07002087 RunDumpsys("DUMPSYS", {"vcn_management"}, CommandOptions::WithTimeout(90).Build(),
2088 SEC_TO_MSEC(10));
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08002089 if (include_sensitive_info) {
2090 // Carrier apps' services will be dumped below in dumpsys activity service all-non-platform.
2091 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
2092 SEC_TO_MSEC(10));
2093 } else {
2094 // If the caller is a carrier app and has a carrier service, dump it here since we aren't
2095 // running dumpsys activity service all-non-platform below. Due to the increased output, we
2096 // give a higher timeout as well.
2097 RunDumpsys("DUMPSYS", {"carrier_config", "--requesting-package", calling_package},
2098 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(30));
2099 }
2100 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002101 RunDumpsys("DUMPSYS", {"netpolicy"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2102 RunDumpsys("DUMPSYS", {"network_management"}, CommandOptions::WithTimeout(90).Build(),
Sooraj Sasindrane8d98912018-04-20 11:31:55 -07002103 SEC_TO_MSEC(10));
Hunter Knepshield0fe51b12020-03-05 16:58:20 -08002104 RunDumpsys("DUMPSYS", {"telephony.registry"}, CommandOptions::WithTimeout(90).Build(),
2105 SEC_TO_MSEC(10));
Jack Yu773cc032023-03-16 22:43:39 -07002106 RunDumpsys("DUMPSYS", {"isub"}, CommandOptions::WithTimeout(90).Build(),
2107 SEC_TO_MSEC(10));
Grant Menke9bf3b2b2023-02-24 13:11:07 -08002108 RunDumpsys("DUMPSYS", {"telecom"}, CommandOptions::WithTimeout(90).Build(),
2109 SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002110 if (include_sensitive_info) {
2111 // Contains raw IP addresses, omit from reports on user builds.
2112 RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2113 // Contains raw destination IP/MAC addresses, omit from reports on user builds.
2114 RunDumpsys("DUMPSYS", {"connmetrics"}, CommandOptions::WithTimeout(90).Build(),
2115 SEC_TO_MSEC(10));
2116 // Contains package/component names, omit from reports on user builds.
2117 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
2118 SEC_TO_MSEC(10));
2119 // Contains package names, but should be relatively simple to remove them (also contains
2120 // UIDs already), omit from reports on user builds.
2121 RunDumpsys("BATTERYSTATS", {"deviceidle"}, CommandOptions::WithTimeout(90).Build(),
2122 SEC_TO_MSEC(10));
2123 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002124
2125 printf("========================================================\n");
2126 printf("== Running Application Services\n");
2127 printf("========================================================\n");
2128
2129 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
2130
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002131 if (include_sensitive_info) {
2132 printf("========================================================\n");
2133 printf("== Running Application Services (non-platform)\n");
2134 printf("========================================================\n");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002135
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002136 // Contains package/component names and potential PII, omit from reports on user builds.
2137 // To get dumps of the active CarrierService(s) on user builds, we supply an argument to the
2138 // carrier_config dumpsys instead.
2139 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
2140 DUMPSYS_COMPONENTS_OPTIONS);
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002141
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002142 printf("========================================================\n");
2143 printf("== Checkins\n");
2144 printf("========================================================\n");
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002145
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002146 // Contains package/component names, omit from reports on user builds.
2147 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
2148 }
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002149
2150 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07002151 printf("== dumpstate: done (id %d)\n", ds.id_);
2152 printf("========================================================\n");
Rhed Jaob5685b32020-08-14 17:19:17 +08002153
2154 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002155 WaitForTask(std::move(dump_board));
Rhed Jaob5685b32020-08-14 17:19:17 +08002156 } else {
2157 RUN_SLOW_FUNCTION_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
2158 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002159}
2160
mukesh agrawal253dad42018-01-23 21:59:59 -08002161// This method collects dumpsys for wifi debugging only
2162static void DumpstateWifiOnly() {
2163 DurationReporter duration_reporter("DUMPSTATE");
2164
Rhed Jaob5685b32020-08-14 17:19:17 +08002165 DumpstateRadioAsRoot();
2166 if (!DropRootUser()) {
2167 return;
2168 }
2169
2170 // Starts thread pool after the root user is dropped. Only one additional
2171 // thread is needed for DumpHals in the DumpstateRadioCommon.
2172 if (ds.dump_pool_) {
2173 ds.dump_pool_->start(/*thread_counts =*/1);
2174 }
2175
mukesh agrawal253dad42018-01-23 21:59:59 -08002176 DumpstateRadioCommon();
2177
2178 printf("========================================================\n");
2179 printf("== Android Framework Services\n");
2180 printf("========================================================\n");
2181
2182 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2183 SEC_TO_MSEC(10));
2184 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
2185 SEC_TO_MSEC(10));
2186
2187 printf("========================================================\n");
2188 printf("== dumpstate: done (id %d)\n", ds.id_);
2189 printf("========================================================\n");
2190}
2191
Elis Elliott8e401ad2023-08-08 11:18:59 +00002192// Collects a lightweight dumpstate to be used for debugging onboarding related flows.
2193static void DumpstateOnboardingOnly() {
2194 ds.AddDir(LOGPERSIST_DATA_DIR, false);
2195}
2196
Christopher Ferris83e0e842024-05-31 13:13:34 -07002197static std::string GetTimestamp(const timespec& ts) {
2198 tm tm;
2199 localtime_r(&ts.tv_sec, &tm);
2200
2201 // Reserve enough space for the entire time string, includes the space
2202 // for the '\0' to make the calculations below easier by using size for
2203 // the total string size.
2204 std::string str(sizeof("1970-01-01 00:00:00.123456789+0830"), '\0');
2205 size_t n = strftime(str.data(), str.size(), "%F %H:%M", &tm);
2206 if (n == 0) {
2207 return "TIMESTAMP FAILURE";
2208 }
2209 int num_chars = snprintf(&str[n], str.size() - n, ":%02d.%09ld", tm.tm_sec, ts.tv_nsec);
2210 if (num_chars > str.size() - n) {
2211 return "TIMESTAMP FAILURE";
2212 }
2213 n += static_cast<size_t>(num_chars);
2214 if (strftime(&str[n], str.size() - n, "%z", &tm) == 0) {
2215 return "TIMESTAMP FAILURE";
2216 }
2217 return str;
2218}
2219
2220static std::string GetCmdline(pid_t pid) {
2221 std::string cmdline;
2222 if (!android::base::ReadFileToString(android::base::StringPrintf("/proc/%d/cmdline", pid),
2223 &cmdline)) {
2224 return "UNKNOWN";
2225 }
2226 // There are '\0' terminators between arguments, convert them to spaces.
2227 // But start by skipping all trailing '\0' values.
2228 size_t cur = cmdline.size() - 1;
2229 while (cur != 0 && cmdline[cur] == '\0') {
2230 cur--;
2231 }
2232 if (cur == 0) {
2233 return "UNKNOWN";
2234 }
2235 while ((cur = cmdline.rfind('\0', cur)) != std::string::npos) {
2236 cmdline[cur] = ' ';
2237 }
2238 return cmdline;
2239}
2240
2241static void DumpPidHeader(int fd, pid_t pid, const timespec& ts) {
2242 // For consistency, the header to this message matches the one
2243 // dumped by debuggerd.
2244 dprintf(fd, "\n----- pid %d at %s -----\n", pid, GetTimestamp(ts).c_str());
2245 dprintf(fd, "Cmd line: %s\n", GetCmdline(pid).c_str());
2246}
2247
2248static void DumpPidFooter(int fd, pid_t pid) {
2249 // For consistency, the footer to this message matches the one
2250 // dumped by debuggerd.
2251 dprintf(fd, "----- end %d -----\n", pid);
2252}
2253
2254static bool DumpBacktrace(int fd, pid_t pid, bool is_java_process) {
2255 int ret = dump_backtrace_to_file_timeout(
2256 pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace, 3, fd);
2257 if (ret == -1 && is_java_process) {
2258 // Tried to unwind as a java process, try a native unwind.
2259 dprintf(fd, "Java unwind failed for pid %d, trying a native unwind.\n", pid);
2260 ret = dump_backtrace_to_file_timeout(pid, kDebuggerdNativeBacktrace, 3, fd);
2261 }
2262 return ret != -1;
2263}
2264
Nandana Duttcf419a72019-03-14 10:40:17 +00002265Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
Gavin Corkery789d7a52021-02-24 23:52:35 +00002266 const std::string temp_file_pattern = ds.bugreport_internal_dir_ + "/dumptrace_XXXXXX";
Nandana Duttfaafd522019-03-11 09:23:09 +00002267 const size_t buf_size = temp_file_pattern.length() + 1;
2268 std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
2269 memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
2270
2271 // Create a new, empty file to receive all trace dumps.
2272 //
2273 // TODO: This can be simplified once we remove support for the old style
2274 // dumps. We can have a file descriptor passed in to dump_traces instead
2275 // of creating a file, closing it and then reopening it again.
2276 android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
2277 if (fd < 0) {
2278 MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002279 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002280 }
2281
2282 // Nobody should have access to this temporary file except dumpstate, but we
2283 // temporarily grant 'read' to 'others' here because this file is created
2284 // when tombstoned is still running as root, but dumped after dropping. This
2285 // can go away once support for old style dumping has.
2286 const int chmod_ret = fchmod(fd, 0666);
2287 if (chmod_ret < 0) {
2288 MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002289 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002290 }
2291
2292 std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
2293 if (proc.get() == nullptr) {
2294 MYLOGE("opendir /proc failed: %s\n", strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002295 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002296 }
2297
2298 // Number of times process dumping has timed out. If we encounter too many
2299 // failures, we'll give up.
2300 int timeout_failures = 0;
2301 bool dalvik_found = false;
2302
Jayant Chowdharya0a8eb22022-05-20 03:30:09 +00002303 const std::set<int> hal_pids = get_interesting_pids();
Nandana Duttfaafd522019-03-11 09:23:09 +00002304
2305 struct dirent* d;
2306 while ((d = readdir(proc.get()))) {
Nandana Duttcf419a72019-03-14 10:40:17 +00002307 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttfaafd522019-03-11 09:23:09 +00002308 int pid = atoi(d->d_name);
2309 if (pid <= 0) {
2310 continue;
2311 }
2312
2313 const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
2314 std::string exe;
2315 if (!android::base::Readlink(link_name, &exe)) {
2316 continue;
2317 }
2318
2319 bool is_java_process;
2320 if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
2321 // Don't bother dumping backtraces for the zygote.
2322 if (IsZygote(pid)) {
2323 continue;
2324 }
2325
2326 dalvik_found = true;
2327 is_java_process = true;
2328 } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
2329 is_java_process = false;
2330 } else {
2331 // Probably a native process we don't care about, continue.
2332 continue;
2333 }
2334
2335 // If 3 backtrace dumps fail in a row, consider debuggerd dead.
2336 if (timeout_failures == 3) {
2337 dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
2338 break;
2339 }
2340
Christopher Ferris83e0e842024-05-31 13:13:34 -07002341 timespec start_timespec;
2342 clock_gettime(CLOCK_REALTIME, &start_timespec);
2343 if (IsCached(pid)) {
2344 DumpPidHeader(fd, pid, start_timespec);
2345 dprintf(fd, "Process is cached, skipping backtrace due to high chance of timeout.\n");
2346 DumpPidFooter(fd, pid);
2347 continue;
2348 }
Nandana Duttfaafd522019-03-11 09:23:09 +00002349
Christopher Ferris83e0e842024-05-31 13:13:34 -07002350 const uint64_t start = Nanotime();
2351 if (!DumpBacktrace(fd, pid, is_java_process)) {
2352 if (IsCached(pid)) {
2353 DumpPidHeader(fd, pid, start_timespec);
2354 dprintf(fd, "Backtrace failed, but process has become cached.\n");
2355 DumpPidFooter(fd, pid);
2356 continue;
2357 }
2358
2359 DumpPidHeader(fd, pid, start_timespec);
2360 dprintf(fd, "Backtrace gathering failed, likely due to a timeout.\n");
2361 DumpPidFooter(fd, pid);
2362
2363 dprintf(fd, "\n[dump %s stack %d: %.3fs elapsed]\n",
2364 is_java_process ? "dalvik" : "native", pid,
2365 (float)(Nanotime() - start) / NANOS_PER_SEC);
Nandana Duttfaafd522019-03-11 09:23:09 +00002366 timeout_failures++;
2367 continue;
2368 }
2369
2370 // We've successfully dumped stack traces, reset the failure count
2371 // and write a summary of the elapsed time to the file and continue with the
2372 // next process.
2373 timeout_failures = 0;
2374
2375 dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
2376 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
2377 }
2378
2379 if (!dalvik_found) {
2380 MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
2381 }
2382
Nandana Duttcf419a72019-03-14 10:40:17 +00002383 *path = file_name_buf.release();
2384 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002385}
2386
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002387static dumpstate_hal_hidl::DumpstateMode GetDumpstateHalModeHidl(
2388 const Dumpstate::BugreportMode bugreport_mode) {
2389 switch (bugreport_mode) {
2390 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2391 return dumpstate_hal_hidl::DumpstateMode::FULL;
2392 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2393 return dumpstate_hal_hidl::DumpstateMode::INTERACTIVE;
2394 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2395 return dumpstate_hal_hidl::DumpstateMode::REMOTE;
2396 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2397 return dumpstate_hal_hidl::DumpstateMode::WEAR;
2398 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2399 return dumpstate_hal_hidl::DumpstateMode::CONNECTIVITY;
2400 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2401 return dumpstate_hal_hidl::DumpstateMode::WIFI;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002402 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002403 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2404 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2405 }
2406 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2407}
2408
2409static dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode GetDumpstateHalModeAidl(
2410 const Dumpstate::BugreportMode bugreport_mode) {
2411 switch (bugreport_mode) {
2412 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2413 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::FULL;
2414 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2415 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::INTERACTIVE;
2416 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2417 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::REMOTE;
2418 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2419 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WEAR;
2420 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2421 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::CONNECTIVITY;
2422 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2423 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WIFI;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002424 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002425 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2426 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2427 }
2428 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2429}
2430
2431static void DoDumpstateBoardHidl(
2432 const sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_1_0,
2433 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2434 const Dumpstate::BugreportMode bugreport_mode,
2435 const size_t timeout_sec) {
2436
2437 using ScopedNativeHandle =
2438 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
2439 ScopedNativeHandle handle(native_handle_create(static_cast<int>(dumpstate_fds.size()), 0),
2440 [](native_handle_t* handle) {
2441 // we don't close file handle's here
2442 // via native_handle_close(handle)
2443 // instead we let dumpstate_fds close the file handles when
2444 // dumpstate_fds gets destroyed
2445 native_handle_delete(handle);
2446 });
2447 if (handle == nullptr) {
2448 MYLOGE("Could not create native_handle for dumpstate HAL\n");
2449 return;
2450 }
2451
2452 for (size_t i = 0; i < dumpstate_fds.size(); i++) {
2453 handle.get()->data[i] = dumpstate_fds[i].get();
2454 }
2455
2456 // Prefer version 1.1 if available. New devices launching with R are no longer allowed to
2457 // implement just 1.0.
2458 const char* descriptor_to_kill;
2459 using DumpstateBoardTask = std::packaged_task<bool()>;
2460 DumpstateBoardTask dumpstate_board_task;
2461 sp<dumpstate_hal_hidl::IDumpstateDevice> dumpstate_hal(
2462 dumpstate_hal_hidl::IDumpstateDevice::castFrom(dumpstate_hal_1_0));
2463 if (dumpstate_hal != nullptr) {
2464 MYLOGI("Using IDumpstateDevice v1.1 HIDL HAL");
2465
2466 dumpstate_hal_hidl::DumpstateMode dumpstate_hal_mode =
2467 GetDumpstateHalModeHidl(bugreport_mode);
2468
2469 descriptor_to_kill = dumpstate_hal_hidl::IDumpstateDevice::descriptor;
2470 dumpstate_board_task =
2471 DumpstateBoardTask([timeout_sec, dumpstate_hal_mode, dumpstate_hal, &handle]() -> bool {
2472 ::android::hardware::Return<dumpstate_hal_hidl::DumpstateStatus> status =
2473 dumpstate_hal->dumpstateBoard_1_1(handle.get(), dumpstate_hal_mode,
2474 SEC_TO_MSEC(timeout_sec));
2475 if (!status.isOk()) {
2476 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2477 return false;
2478 } else if (status != dumpstate_hal_hidl::DumpstateStatus::OK) {
2479 MYLOGE("dumpstateBoard failed with DumpstateStatus::%s\n",
2480 dumpstate_hal_hidl::toString(status).c_str());
2481 return false;
2482 }
2483 return true;
2484 });
2485 } else {
2486 MYLOGI("Using IDumpstateDevice v1.0 HIDL HAL");
2487
2488 descriptor_to_kill = dumpstate_hal_hidl_1_0::IDumpstateDevice::descriptor;
2489 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal_1_0, &handle]() -> bool {
2490 ::android::hardware::Return<void> status =
2491 dumpstate_hal_1_0->dumpstateBoard(handle.get());
2492 if (!status.isOk()) {
2493 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2494 return false;
2495 }
2496 return true;
2497 });
2498 }
2499 auto result = dumpstate_board_task.get_future();
2500 std::thread(std::move(dumpstate_board_task)).detach();
2501
2502 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2503 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2504 if (!android::base::SetProperty(
2505 "ctl.interface_restart",
2506 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2507 MYLOGE("Couldn't restart dumpstate HAL\n");
2508 }
2509 }
2510 // Wait some time for init to kill dumpstate vendor HAL
2511 constexpr size_t killing_timeout_sec = 10;
2512 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2513 MYLOGE(
2514 "killing dumpstateBoard timed out after %zus, continue and "
2515 "there might be racing in content\n",
2516 killing_timeout_sec);
2517 }
2518}
2519
2520static void DoDumpstateBoardAidl(
2521 const std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal,
2522 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2523 const Dumpstate::BugreportMode bugreport_mode, const size_t timeout_sec) {
2524 MYLOGI("Using IDumpstateDevice AIDL HAL");
2525
2526 const char* descriptor_to_kill;
2527 using DumpstateBoardTask = std::packaged_task<bool()>;
2528 DumpstateBoardTask dumpstate_board_task;
2529 dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode dumpstate_hal_mode =
2530 GetDumpstateHalModeAidl(bugreport_mode);
2531
2532 descriptor_to_kill = dumpstate_hal_aidl::IDumpstateDevice::descriptor;
2533 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal, &dumpstate_fds, dumpstate_hal_mode,
2534 timeout_sec]() -> bool {
2535 auto status = dumpstate_hal->dumpstateBoard(dumpstate_fds, dumpstate_hal_mode, timeout_sec);
2536
2537 if (!status.isOk()) {
2538 MYLOGE("dumpstateBoard failed: %s\n", status.getDescription().c_str());
2539 return false;
2540 }
2541 return true;
2542 });
2543 auto result = dumpstate_board_task.get_future();
2544 std::thread(std::move(dumpstate_board_task)).detach();
2545
2546 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2547 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2548 if (!android::base::SetProperty(
2549 "ctl.interface_restart",
2550 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2551 MYLOGE("Couldn't restart dumpstate HAL\n");
2552 }
2553 }
2554 // Wait some time for init to kill dumpstate vendor HAL
2555 constexpr size_t killing_timeout_sec = 10;
2556 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2557 MYLOGE(
2558 "killing dumpstateBoard timed out after %zus, continue and "
2559 "there might be racing in content\n",
2560 killing_timeout_sec);
2561 }
2562}
2563
2564static std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> GetDumpstateBoardAidlService() {
2565 const std::string aidl_instance_name =
2566 std::string(dumpstate_hal_aidl::IDumpstateDevice::descriptor) + "/default";
2567
2568 if (!AServiceManager_isDeclared(aidl_instance_name.c_str())) {
2569 return nullptr;
2570 }
2571
2572 ndk::SpAIBinder dumpstateBinder(AServiceManager_waitForService(aidl_instance_name.c_str()));
2573
2574 return dumpstate_hal_aidl::IDumpstateDevice::fromBinder(dumpstateBinder);
2575}
2576
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002577void Dumpstate::DumpstateBoard(int out_fd) {
2578 dprintf(out_fd, "========================================================\n");
2579 dprintf(out_fd, "== Board\n");
2580 dprintf(out_fd, "========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08002581
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002582 /*
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002583 * mount debugfs for non-user builds with ro.product.debugfs_restrictions.enabled
Hridya Valsaraju51101602021-04-02 14:32:46 -07002584 * set to true and unmount it after invoking dumpstateBoard_* methods.
2585 * This is to enable debug builds to not have debugfs mounted during runtime.
2586 * It will also ensure that debugfs is only accessed by the dumpstate HAL.
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002587 */
Hridya Valsaraju51101602021-04-02 14:32:46 -07002588 auto mount_debugfs =
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002589 android::base::GetBoolProperty("ro.product.debugfs_restrictions.enabled", false);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002590 if (mount_debugfs) {
2591 RunCommand("mount debugfs", {"mount", "-t", "debugfs", "debugfs", "/sys/kernel/debug"},
2592 AS_ROOT_20);
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002593 RunCommand("chmod debugfs", {"chmod", "0755", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002594 }
2595
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002596 std::vector<std::string> paths;
2597 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07002598 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002599 paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
2600 kDumpstateBoardFiles[i].c_str()));
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002601 remover.emplace_back(android::base::make_scope_guard(
2602 std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002603 }
Jie Song9fbfad02017-06-20 16:29:42 -07002604
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002605 // get dumpstate HAL AIDL implementation
2606 std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal_handle_aidl(
2607 GetDumpstateBoardAidlService());
2608 if (dumpstate_hal_handle_aidl == nullptr) {
2609 MYLOGI("No IDumpstateDevice AIDL implementation\n");
2610 }
2611
2612 // get dumpstate HAL HIDL implementation, only if AIDL HAL implementation not found
2613 sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_handle_hidl_1_0 = nullptr;
2614 if (dumpstate_hal_handle_aidl == nullptr) {
2615 dumpstate_hal_handle_hidl_1_0 = dumpstate_hal_hidl_1_0::IDumpstateDevice::getService();
2616 if (dumpstate_hal_handle_hidl_1_0 == nullptr) {
2617 MYLOGI("No IDumpstateDevice HIDL implementation\n");
2618 }
2619 }
2620
2621 // if neither HIDL nor AIDL implementation found, then return
2622 if (dumpstate_hal_handle_hidl_1_0 == nullptr && dumpstate_hal_handle_aidl == nullptr) {
2623 MYLOGE("Could not find IDumpstateDevice implementation\n");
Wei Wang587eac92018-04-05 12:17:20 -07002624 return;
2625 }
2626
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002627 // this is used to hold the file descriptors and when this variable goes out of scope
2628 // the file descriptors are closed
2629 std::vector<::ndk::ScopedFileDescriptor> dumpstate_fds;
Wei Wang587eac92018-04-05 12:17:20 -07002630
Nandana Dutt5c390032019-03-12 10:52:56 +00002631 // TODO(128270426): Check for consent in between?
Wei Wang587eac92018-04-05 12:17:20 -07002632 for (size_t i = 0; i < paths.size(); i++) {
2633 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
2634
2635 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
2636 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
2637 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
2638 if (fd < 0) {
2639 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
2640 return;
2641 }
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002642
2643 dumpstate_fds.emplace_back(fd.release());
2644 // we call fd.release() here to make sure "fd" does not get closed
2645 // after "fd" goes out of scope after this block.
2646 // "fd" will be closed when "dumpstate_fds" goes out of scope
2647 // i.e. when we exit this function
Wei Wang587eac92018-04-05 12:17:20 -07002648 }
2649
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002650 // Given that bugreport is required to diagnose failures, it's better to set an arbitrary amount
2651 // of timeout for IDumpstateDevice than to block the rest of bugreport. In the timeout case, we
2652 // will kill the HAL and grab whatever it dumped in time.
Michael Eastwood8523ea02022-03-10 16:33:08 -08002653 constexpr size_t timeout_sec = 45;
Wei Wang587eac92018-04-05 12:17:20 -07002654
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002655 if (dumpstate_hal_handle_aidl != nullptr) {
2656 DoDumpstateBoardAidl(dumpstate_hal_handle_aidl, dumpstate_fds, options_->bugreport_mode,
2657 timeout_sec);
2658 } else if (dumpstate_hal_handle_hidl_1_0 != nullptr) {
2659 // run HIDL HAL only if AIDL HAL not found
2660 DoDumpstateBoardHidl(dumpstate_hal_handle_hidl_1_0, dumpstate_fds, options_->bugreport_mode,
2661 timeout_sec);
Wei Wang587eac92018-04-05 12:17:20 -07002662 }
2663
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002664 if (mount_debugfs) {
Hridya Valsaraju51101602021-04-02 14:32:46 -07002665 auto keep_debugfs_mounted =
2666 android::base::GetProperty("persist.dbg.keep_debugfs_mounted", "");
2667 if (keep_debugfs_mounted.empty())
2668 RunCommand("unmount debugfs", {"umount", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002669 }
2670
Wei Wang587eac92018-04-05 12:17:20 -07002671 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
2672 for (size_t i = 0; i < paths.size(); i++) {
2673 struct stat s;
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002674 if (fstat(dumpstate_fds[i].get(), &s) == -1) {
2675 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(), strerror(errno));
Wei Wang587eac92018-04-05 12:17:20 -07002676 file_sizes[i] = -1;
2677 continue;
2678 }
2679 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002680 }
2681
2682 for (size_t i = 0; i < paths.size(); i++) {
2683 if (file_sizes[i] == -1) {
2684 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002685 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002686 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07002687 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002688 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002689 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002690 remover[i].Disable();
2691 EnqueueAddZipEntryAndCleanupIfNeeded(kDumpstateBoardFiles[i], paths[i]);
2692 dprintf(out_fd, "*** See %s entry ***\n", kDumpstateBoardFiles[i].c_str());
Jie Song9fbfad02017-06-20 16:29:42 -07002693 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08002694}
2695
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002696static void ShowUsage() {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002697 fprintf(stderr,
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002698 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o directory] [-p] "
2699 "[-s] [-S] [-q] [-P] [-R] [-L] [-V version]\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002700 " -h: display this help message\n"
2701 " -b: play sound file instead of vibrate, at beginning of job\n"
2702 " -e: play sound file instead of vibrate, at end of job\n"
mhasank2d75c442020-06-11 15:05:25 -07002703 " -o: write to custom directory (only in limited mode)\n"
Abhijeet Kaurbb55a3b2019-06-13 18:07:25 +01002704 " -p: capture screenshot to filename.png\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002705 " -s: write zipped file to control socket (for init)\n"
2706 " -S: write file location to control socket (for init)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002707 " -q: disable vibrate\n"
Abhijeet Kaure370d682019-10-01 16:49:30 +01002708 " -P: send broadcast when started and do progress updates\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002709 " -R: take bugreport in remote mode (shouldn't be used with -P)\n"
Nandana Dutt235864b2019-01-22 12:10:16 +00002710 " -w: start binder service and make it wait for a call to startBugreport\n"
mhasankd451a472020-05-26 18:02:39 -07002711 " -L: output limited information that is safe for submission in feedback reports\n"
Felipe Lemed071c682016-10-20 16:48:00 -07002712 " -v: prints the dumpstate header and exit\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002713}
2714
Wei Liuf87959e2016-08-26 14:51:42 -07002715static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07002716 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07002717}
2718
Felipe Leme1d486fe2016-10-14 18:06:47 -07002719bool Dumpstate::FinishZipFile() {
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002720 // Runs all enqueued adding zip entry and cleanup tasks before finishing the zip file.
2721 if (zip_entry_tasks_) {
2722 zip_entry_tasks_->run(/* do_cancel = */false);
2723 }
2724
Felipe Leme9a523ae2016-10-20 15:10:33 -07002725 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07002726 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07002727 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002728 // Final timestamp
2729 char date[80];
2730 time_t the_real_now_please_stand_up = time(nullptr);
2731 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002732 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002733 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002734
Felipe Leme9a523ae2016-10-20 15:10:33 -07002735 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002736 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08002737 return false;
2738 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07002739 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002740 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08002741 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08002742 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08002743
Felipe Leme0f3fb202016-06-10 17:10:53 -07002744 // Add log file (which contains stderr output) to zip...
2745 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002746 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07002747 MYLOGE("Failed to add dumpstate log to .zip file\n");
2748 return false;
2749 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002750 // TODO: Should truncate the existing file.
2751 // ... and re-open it for further logging.
Nandana Dutta344cb62019-02-22 15:12:35 +00002752 if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
2753 return false;
2754 }
Felipe Leme0f3fb202016-06-10 17:10:53 -07002755 fprintf(stderr, "\n");
2756
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002757 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07002758 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002759 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002760 return false;
2761 }
2762
Felipe Leme1d486fe2016-10-14 18:06:47 -07002763 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
2764 ds.zip_file.reset(nullptr);
2765
Felipe Lemee9d2c542016-11-15 11:48:26 -08002766 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002767 android::os::UnlinkAndLogOnError(tmp_path_);
Felipe Lemec4eee562016-04-21 15:42:55 -07002768
Felipe Leme1e9edc62015-12-21 16:02:13 -08002769 return true;
2770}
Felipe Leme6e01fa62015-11-11 19:35:14 -08002771
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00002772static void SendBroadcast(const std::string& action,
2773 const std::vector<std::string>& args,
2774 int32_t user_id) {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002775 // clang-format off
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00002776 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user",
2777 std::to_string(user_id), "--receiver-foreground",
2778 "--receiver-include-background", "-a", action};
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002779 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08002780
2781 am.insert(am.end(), args.begin(), args.end());
2782
Felipe Leme8d2410e2017-02-08 09:46:08 -08002783 RunCommand("", am,
2784 CommandOptions::WithTimeout(20)
2785 .Log("Sending broadcast: '%s'\n")
2786 .Always()
2787 .DropRoot()
2788 .RedirectStderr()
2789 .Build());
2790}
2791
Felipe Leme35b8cf12017-02-10 15:47:29 -08002792static void Vibrate(int duration_ms) {
2793 // clang-format off
Lais Andrade51156962021-02-22 19:21:35 +00002794 std::vector<std::string> args = {"cmd", "vibrator_manager", "synced", "-f", "-d", "dumpstate",
2795 "oneshot", std::to_string(duration_ms)};
2796 RunCommand("", args,
Felipe Leme35b8cf12017-02-10 15:47:29 -08002797 CommandOptions::WithTimeout(10)
2798 .Log("Vibrate: '%s'\n")
2799 .Always()
2800 .Build());
2801 // clang-format on
2802}
2803
Nandana Dutt979388e2018-11-30 16:48:55 +00002804static void MaybeResolveSymlink(std::string* path) {
2805 std::string resolved_path;
2806 if (android::base::Readlink(*path, &resolved_path)) {
2807 *path = resolved_path;
2808 }
2809}
2810
Nandana Dutt4be45d12018-09-26 15:04:23 +01002811/*
2812 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002813 * and adds the version file. Return false if zip_file could not be open to write.
Nandana Dutt4be45d12018-09-26 15:04:23 +01002814 */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002815static bool PrepareToWriteToFile() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002816 MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2817
Nandana Dutt4be45d12018-09-26 15:04:23 +01002818 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2819 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002820 ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002821 char date[80];
2822 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2823 ds.name_ = date;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002824
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002825 if (ds.options_->telephony_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002826 ds.base_name_ += "-telephony";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002827 } else if (ds.options_->wifi_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002828 ds.base_name_ += "-wifi";
2829 }
2830
Paul Chang0d2aad72020-02-13 20:04:03 +08002831 if (ds.options_->do_screenshot) {
Nandana Dutt9d17b942020-03-26 10:02:59 +00002832 ds.screenshot_path_ = ds.GetPath(ds.CalledByApi() ? "-png.tmp" : ".png");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002833 }
2834 ds.tmp_path_ = ds.GetPath(".tmp");
2835 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2836
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01002837 std::string destination = ds.CalledByApi()
Nandana Dutt54dbd672019-01-11 12:58:05 +00002838 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
Nandana Dutt9a76d202019-01-21 15:56:48 +00002839 : ds.bugreport_internal_dir_.c_str();
Nandana Dutt4be45d12018-09-26 15:04:23 +01002840 MYLOGD(
Nandana Dutt235c6672019-11-14 15:22:32 +00002841 "Bugreport dir: [%s] "
2842 "Base name: [%s] "
2843 "Suffix: [%s] "
2844 "Log path: [%s] "
2845 "Temporary path: [%s] "
2846 "Screenshot path: [%s]\n",
Nandana Dutt9a76d202019-01-21 15:56:48 +00002847 destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2848 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002849
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002850 ds.path_ = ds.GetPath(ds.CalledByApi() ? "-zip.tmp" : ".zip");
2851 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2852 create_parent_dirs(ds.path_.c_str());
2853 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2854 if (ds.zip_file == nullptr) {
2855 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2856 return false;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002857 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002858 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2859 ds.AddTextZipEntry("version.txt", ds.version_);
2860 return true;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002861}
2862
2863/*
Abhijeet Kaure370d682019-10-01 16:49:30 +01002864 * Finalizes writing to the file by zipping the tmp file to the final location,
Nandana Dutt4be45d12018-09-26 15:04:23 +01002865 * printing zipped file status, etc.
2866 */
2867static void FinalizeFile() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002868 bool do_text_file = !ds.FinishZipFile();
2869 if (do_text_file) {
2870 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002871 }
mhasank2d75c442020-06-11 15:05:25 -07002872
2873 std::string final_path = ds.path_;
2874 if (ds.options_->OutputToCustomFile()) {
mhasank3a4cfb42020-06-15 18:06:43 -07002875 final_path = ds.GetPath(ds.options_->out_dir, ".zip");
mhasank2d75c442020-06-11 15:05:25 -07002876 android::os::CopyFileToFile(ds.path_, final_path);
2877 }
2878
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002879 if (ds.options_->stream_to_socket) {
2880 android::os::CopyFileToFd(ds.path_, ds.control_socket_fd_);
2881 } else if (ds.options_->progress_updates_to_socket) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002882 if (do_text_file) {
2883 dprintf(ds.control_socket_fd_,
2884 "FAIL:could not create zip file, check %s "
2885 "for more details\n",
2886 ds.log_path_.c_str());
2887 } else {
mhasank2d75c442020-06-11 15:05:25 -07002888 dprintf(ds.control_socket_fd_, "OK:%s\n", final_path.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002889 }
2890 }
2891}
2892
Nandana Dutt4be45d12018-09-26 15:04:23 +01002893
Nandana Dutt58d72e22018-11-16 10:30:48 +00002894static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2895 switch (mode) {
2896 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2897 return "BUGREPORT_FULL";
2898 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2899 return "BUGREPORT_INTERACTIVE";
2900 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2901 return "BUGREPORT_REMOTE";
2902 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2903 return "BUGREPORT_WEAR";
2904 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2905 return "BUGREPORT_TELEPHONY";
2906 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2907 return "BUGREPORT_WIFI";
Elis Elliott8e401ad2023-08-08 11:18:59 +00002908 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
2909 return "BUGREPORT_ONBOARDING";
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002910 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2911 return "BUGREPORT_DEFAULT";
Nandana Dutt58d72e22018-11-16 10:30:48 +00002912 }
2913}
2914
Steven Leeb573eb82022-11-29 22:31:35 +08002915static bool IsConsentlessBugreportAllowed(const Dumpstate::DumpOptions& options) {
2916 // only BUGREPORT_TELEPHONY does not allow using consentless bugreport
2917 return !options.telephony_only;
2918}
2919
Paul Changf59c2b72020-03-10 02:08:55 +08002920static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options,
2921 bool is_screenshot_requested) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002922 // Modify com.android.shell.BugreportProgressService#isDefaultScreenshotRequired as well for
2923 // default system screenshots.
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002924 options->bugreport_mode = mode;
2925 options->bugreport_mode_string = ModeToString(mode);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002926 switch (mode) {
2927 case Dumpstate::BugreportMode::BUGREPORT_FULL:
Paul Changf59c2b72020-03-10 02:08:55 +08002928 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002929 break;
2930 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002931 // Currently, the dumpstate binder is only used by Shell to update progress.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002932 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002933 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002934 break;
2935 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002936 options->do_vibrate = false;
2937 options->is_remote_mode = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002938 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002939 break;
2940 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
Robert Ginda55ecebd2023-04-03 22:53:13 +00002941 options->do_vibrate = false;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002942 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002943 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002944 break;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002945 // TODO(b/148168577) rename TELEPHONY everywhere to CONNECTIVITY.
Nandana Dutt58d72e22018-11-16 10:30:48 +00002946 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002947 options->telephony_only = true;
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002948 options->do_progress_updates = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002949 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002950 break;
2951 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002952 options->wifi_only = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002953 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002954 break;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002955 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
2956 options->onboarding_only = true;
2957 options->do_screenshot = false;
2958 break;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002959 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2960 break;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002961 }
2962}
2963
Nandana Dutt58d72e22018-11-16 10:30:48 +00002964static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
Nandana Dutt235c6672019-11-14 15:22:32 +00002965 MYLOGI(
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002966 "do_vibrate: %d stream_to_socket: %d progress_updates_to_socket: %d do_screenshot: %d "
Rhed Jao25f50e02020-08-20 00:10:32 +08002967 "is_remote_mode: %d show_header_only: %d telephony_only: %d "
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002968 "wifi_only: %d do_progress_updates: %d fd: %d bugreport_mode: %s "
mhasankd451a472020-05-26 18:02:39 -07002969 "limited_only: %d args: %s\n",
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002970 options.do_vibrate, options.stream_to_socket, options.progress_updates_to_socket,
Paul Chang0d2aad72020-02-13 20:04:03 +08002971 options.do_screenshot, options.is_remote_mode, options.show_header_only,
Rhed Jao25f50e02020-08-20 00:10:32 +08002972 options.telephony_only, options.wifi_only,
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002973 options.do_progress_updates, options.bugreport_fd.get(),
2974 options.bugreport_mode_string.c_str(),
2975 options.limited_only, options.args.c_str());
Nandana Dutt58d72e22018-11-16 10:30:48 +00002976}
2977
Nandana Dutt54dbd672019-01-11 12:58:05 +00002978void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
Kean Mariotti306633e2022-09-05 16:30:47 +00002979 int bugreport_flags,
Nandana Dutt54dbd672019-01-11 12:58:05 +00002980 const android::base::unique_fd& bugreport_fd_in,
Paul Changf59c2b72020-03-10 02:08:55 +08002981 const android::base::unique_fd& screenshot_fd_in,
2982 bool is_screenshot_requested) {
Kean Mariotti306633e2022-09-05 16:30:47 +00002983 this->use_predumped_ui_data = bugreport_flags & BugreportFlag::BUGREPORT_USE_PREDUMPED_UI_DATA;
Gavin Corkerya44686c2022-11-23 18:16:51 +00002984 this->is_consent_deferred = bugreport_flags & BugreportFlag::BUGREPORT_FLAG_DEFER_CONSENT;
Nandana Dutt54dbd672019-01-11 12:58:05 +00002985 // Duplicate the fds because the passed in fds don't outlive the binder transaction.
Todd Frederick621533f2022-03-26 02:54:17 +00002986 bugreport_fd.reset(fcntl(bugreport_fd_in.get(), F_DUPFD_CLOEXEC, 0));
2987 screenshot_fd.reset(fcntl(screenshot_fd_in.get(), F_DUPFD_CLOEXEC, 0));
Nandana Dutt58d72e22018-11-16 10:30:48 +00002988
Paul Changf59c2b72020-03-10 02:08:55 +08002989 SetOptionsFromMode(bugreport_mode, this, is_screenshot_requested);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002990}
2991
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002992Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
2993 RunStatus status = RunStatus::OK;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002994 int c;
mhasankd451a472020-05-26 18:02:39 -07002995 while ((c = getopt(argc, argv, "dho:svqzpLPBRSV:w")) != -1) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002996 switch (c) {
2997 // clang-format off
mhasank3a4cfb42020-06-15 18:06:43 -07002998 case 'o': out_dir = optarg; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002999 case 's': stream_to_socket = true; break;
3000 case 'S': progress_updates_to_socket = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003001 case 'v': show_header_only = true; break;
3002 case 'q': do_vibrate = false; break;
Paul Chang0d2aad72020-02-13 20:04:03 +08003003 case 'p': do_screenshot = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003004 case 'P': do_progress_updates = true; break;
3005 case 'R': is_remote_mode = true; break;
mhasankd451a472020-05-26 18:02:39 -07003006 case 'L': limited_only = true; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003007 case 'V':
3008 case 'd':
3009 case 'z':
3010 // compatibility no-op
3011 break;
Nandana Dutt235864b2019-01-22 12:10:16 +00003012 case 'w':
3013 // This was already processed
3014 break;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003015 case 'h':
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003016 status = RunStatus::HELP;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003017 break;
3018 default:
3019 fprintf(stderr, "Invalid option: %c\n", c);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003020 status = RunStatus::INVALID_INPUT;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003021 break;
3022 // clang-format on
3023 }
3024 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08003025
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003026 for (int i = 0; i < argc; i++) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003027 args += argv[i];
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003028 if (i < argc - 1) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003029 args += " ";
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003030 }
3031 }
3032
3033 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
3034 optind = 1;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003035
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003036 return status;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003037}
3038
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003039bool Dumpstate::DumpOptions::ValidateOptions() const {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003040 if (bugreport_fd.get() != -1 && stream_to_socket) {
Nandana Dutt979388e2018-11-30 16:48:55 +00003041 return false;
3042 }
3043
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003044 if ((progress_updates_to_socket || do_progress_updates) && stream_to_socket) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003045 return false;
3046 }
3047
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003048 if (is_remote_mode && (do_progress_updates || stream_to_socket)) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003049 return false;
3050 }
3051 return true;
3052}
3053
Nandana Dutt197661d2018-11-16 16:40:21 +00003054void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
3055 options_ = std::move(options);
3056}
3057
Abhijeet Kaura407fb82020-03-27 12:51:12 +00003058void Dumpstate::Initialize() {
3059 /* gets the sequential id */
3060 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
3061 id_ = ++last_id;
3062 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
3063}
3064
Nandana Duttd2f5f082019-01-18 17:13:52 +00003065Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
3066 Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
Gavin Corkerya44686c2022-11-23 18:16:51 +00003067 HandleRunStatus(status);
3068 return status;
3069}
3070
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003071Dumpstate::RunStatus Dumpstate::Retrieve(int32_t calling_uid, const std::string& calling_package,
3072 const bool keep_bugreport_on_retrieval) {
3073 Dumpstate::RunStatus status = RetrieveInternal(calling_uid, calling_package,
3074 keep_bugreport_on_retrieval);
Gavin Corkerya44686c2022-11-23 18:16:51 +00003075 HandleRunStatus(status);
3076 return status;
3077}
3078
3079Dumpstate::RunStatus Dumpstate::RetrieveInternal(int32_t calling_uid,
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003080 const std::string& calling_package,
3081 const bool keep_bugreport_on_retrieval) {
Gavin Corkerya44686c2022-11-23 18:16:51 +00003082 consent_callback_ = new ConsentCallback();
3083 const String16 incidentcompanion("incidentcompanion");
3084 sp<android::IBinder> ics(
3085 defaultServiceManager()->checkService(incidentcompanion));
3086 android::String16 package(calling_package.c_str());
3087 if (ics != nullptr) {
3088 MYLOGD("Checking user consent via incidentcompanion service\n");
3089 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
3090 calling_uid, package, String16(), String16(),
3091 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
3092 } else {
3093 MYLOGD(
3094 "Unable to check user consent; incidentcompanion service unavailable\n");
3095 return RunStatus::USER_CONSENT_TIMED_OUT;
3096 }
3097 UserConsentResult consent_result = consent_callback_->getResult();
3098 int timeout_ms = 30 * 1000;
3099 while (consent_result == UserConsentResult::UNAVAILABLE &&
3100 consent_callback_->getElapsedTimeMs() < timeout_ms) {
3101 sleep(1);
3102 consent_result = consent_callback_->getResult();
3103 }
3104 if (consent_result == UserConsentResult::DENIED) {
3105 return RunStatus::USER_CONSENT_DENIED;
3106 }
3107 if (consent_result == UserConsentResult::UNAVAILABLE) {
3108 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3109 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3110 consent_callback_.get());
3111 return RunStatus::USER_CONSENT_TIMED_OUT;
3112 }
3113
3114 bool copy_succeeded =
3115 android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003116
3117 if (copy_succeeded && (!android::app::admin::flags::onboarding_bugreport_v2_enabled()
3118 || !keep_bugreport_on_retrieval)) {
3119 android::os::UnlinkAndLogOnError(path_);
Gavin Corkerya44686c2022-11-23 18:16:51 +00003120 }
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003121
Gavin Corkerya44686c2022-11-23 18:16:51 +00003122 return copy_succeeded ? Dumpstate::RunStatus::OK
3123 : Dumpstate::RunStatus::ERROR;
3124}
3125
3126void Dumpstate::HandleRunStatus(Dumpstate::RunStatus status) {
3127 if (listener_ != nullptr) {
Nandana Duttbabf6c72019-01-15 14:11:12 +00003128 switch (status) {
3129 case Dumpstate::RunStatus::OK:
Gavin Corkerya44686c2022-11-23 18:16:51 +00003130 listener_->onFinished(path_.c_str());
Nandana Duttbabf6c72019-01-15 14:11:12 +00003131 break;
3132 case Dumpstate::RunStatus::HELP:
3133 break;
3134 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003135 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00003136 break;
3137 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003138 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
3139 break;
3140 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3141 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
3142 break;
3143 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
3144 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00003145 break;
3146 }
3147 }
Nandana Duttbabf6c72019-01-15 14:11:12 +00003148}
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003149void Dumpstate::Cancel() {
3150 CleanupTmpFiles();
3151 android::os::UnlinkAndLogOnError(log_path_);
3152 for (int i = 0; i < NUM_OF_DUMPS; i++) {
3153 android::os::UnlinkAndLogOnError(ds.bugreport_internal_dir_ + "/" +
3154 kDumpstateBoardFiles[i]);
3155 }
3156 tombstone_data_.clear();
3157 anr_data_.clear();
Andy Hungd62f7e62024-01-11 15:47:52 -08003158 anr_trace_data_.clear();
Woody Lin20767a92022-11-29 15:50:24 +08003159 shutdown_checkpoints_.clear();
Rhed Jao0daac912020-08-21 14:48:20 +08003160
3161 // Instead of shutdown the pool, we delete temporary files directly since
3162 // shutdown blocking the call.
3163 if (dump_pool_) {
3164 dump_pool_->deleteTempFiles();
3165 }
3166 if (zip_entry_tasks_) {
3167 zip_entry_tasks_->run(/*do_cancel =*/ true);
3168 }
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003169}
3170
Kean Mariotti306633e2022-09-05 16:30:47 +00003171void Dumpstate::PreDumpUiData() {
Kean Mariottica20f2d2023-12-15 09:34:25 +00003172 auto snapshot_system_trace = MaybeSnapshotSystemTraceAsync();
Kean Mariotti306633e2022-09-05 16:30:47 +00003173 MaybeSnapshotUiTraces();
Kean Mariottica20f2d2023-12-15 09:34:25 +00003174 MaybeWaitForSnapshotSystemTrace(std::move(snapshot_system_trace));
Kean Mariotti306633e2022-09-05 16:30:47 +00003175}
3176
Nandana Dutt979388e2018-11-30 16:48:55 +00003177/*
3178 * Dumps relevant information to a bugreport based on the given options.
3179 *
3180 * The bugreport can be dumped to a file or streamed to a socket.
3181 *
3182 * How dumping to file works:
3183 * stdout is redirected to a temporary file. This will later become the main bugreport entry.
3184 * stderr is redirected a log file.
3185 *
3186 * The temporary bugreport is then populated via printfs, dumping contents of files and
3187 * output of commands to stdout.
3188 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003189 * A bunch of other files and dumps are added to the zip archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00003190 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003191 * The temporary bugreport file and the log file also get added to the archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00003192 *
mhasank2d75c442020-06-11 15:05:25 -07003193 * Bugreports are first generated in a local directory and later copied to the caller's fd
3194 * or directory if supplied.
Nandana Dutt979388e2018-11-30 16:48:55 +00003195 */
Nandana Duttd2f5f082019-01-18 17:13:52 +00003196Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
3197 const std::string& calling_package) {
Rhed Jao5377d792020-07-16 17:37:39 +08003198 DurationReporter duration_reporter("RUN INTERNAL", /* logcat_only = */true);
Nandana Dutt979388e2018-11-30 16:48:55 +00003199 LogDumpOptions(*options_);
Nandana Dutt197661d2018-11-16 16:40:21 +00003200 if (!options_->ValidateOptions()) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00003201 MYLOGE("Invalid options specified\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003202 return RunStatus::INVALID_INPUT;
3203 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003204 /* set as high priority, and protect from OOM killer */
3205 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003206
Felipe Lemed071c682016-10-20 16:48:00 -07003207 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07003208 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003209 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003210 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003211 } else {
3212 /* fallback to kernels <= 2.6.35 */
3213 oom_adj = fopen("/proc/self/oom_adj", "we");
3214 if (oom_adj) {
3215 fputs("-17", oom_adj);
3216 fclose(oom_adj);
3217 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003218 }
3219
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003220 if (version_ == VERSION_DEFAULT) {
3221 version_ = VERSION_CURRENT;
Michal Karpinski4db754f2015-12-11 18:04:32 +00003222 }
3223
Chris Morin5a50d482022-02-01 17:41:18 -08003224 if (version_ != VERSION_CURRENT) {
3225 MYLOGE("invalid version requested ('%s'); supported values are: ('%s', '%s')\n",
3226 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003227 return RunStatus::INVALID_INPUT;
Felipe Lemed071c682016-10-20 16:48:00 -07003228 }
3229
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003230 if (options_->show_header_only) {
3231 PrintHeader();
3232 return RunStatus::OK;
Felipe Lemed071c682016-10-20 16:48:00 -07003233 }
3234
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003235 MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n",
3236 calling_uid, calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003237
Felipe Leme7447d7c2016-11-03 18:12:22 -07003238 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003239 std::string stats_path =
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003240 android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003241 progress_.reset(new Progress(stats_path));
Felipe Leme7447d7c2016-11-03 18:12:22 -07003242
Sahana Raof35ed432019-07-12 10:47:52 +01003243 if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
3244 MYLOGE("Failed to acquire wake lock: %s\n", strerror(errno));
3245 } else {
3246 // Wake lock will be released automatically on process death
3247 MYLOGD("Wake lock acquired.\n");
3248 }
3249
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08003250 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07003251
Felipe Lemef0292972016-11-22 13:57:05 -08003252 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07003253 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
3254 }
3255
Kevin Jeonfa64e642023-07-27 11:36:41 -04003256 if (PropertiesHelper::IsStrictRun()) {
3257 MYLOGI(
3258 "Running on strict-run mode, which has shorter timeouts "
3259 "(to disable, call 'setprop dumpstate.strict_run false')\n");
3260 }
3261
Nandana Dutt235c6672019-11-14 15:22:32 +00003262 MYLOGI("dumpstate info: id=%d, args='%s', bugreport_mode= %s bugreport format version: %s\n",
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00003263 id_, options_->args.c_str(), options_->bugreport_mode_string.c_str(), version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08003264
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003265 do_early_screenshot_ = options_->do_progress_updates;
Felipe Lemee338bf62015-12-07 14:03:50 -08003266
Christopher Ferrised9354f2014-10-01 17:35:01 -07003267 // If we are going to use a socket, do it as early as possible
3268 // to avoid timeouts from bugreport.
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003269 if (options_->stream_to_socket || options_->progress_updates_to_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07003270 MYLOGD("Opening control socket\n");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003271 control_socket_fd_ = open_socket_fn_("dumpstate");
Nandana Dutta344cb62019-02-22 15:12:35 +00003272 if (control_socket_fd_ == -1) {
3273 return ERROR;
3274 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003275 if (options_->progress_updates_to_socket) {
3276 options_->do_progress_updates = 1;
3277 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07003278 }
3279
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003280 if (!PrepareToWriteToFile()) {
3281 return ERROR;
3282 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08003283
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003284 // Interactive, wear & telephony modes are default to true.
3285 // and may enable from cli option or when using control socket
3286 if (options_->do_progress_updates) {
3287 // clang-format off
3288 std::vector<std::string> am_args = {
3289 "--receiver-permission", "android.permission.DUMP",
3290 };
3291 // clang-format on
3292 // Send STARTED broadcast for apps that listen to bugreport generation events
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003293 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED",
3294 am_args, multiuser_get_user_id(calling_uid));
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003295 if (options_->progress_updates_to_socket) {
3296 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08003297 }
3298 }
3299
Nick Kralevichf3599b32016-01-25 15:05:16 -08003300 /* read /proc/cmdline before dropping root */
3301 FILE *cmdline = fopen("/proc/cmdline", "re");
3302 if (cmdline) {
3303 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
3304 fclose(cmdline);
3305 }
3306
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003307 if (options_->do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08003308 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05003309 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003310
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003311 if (zip_file != nullptr) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003312 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
3313 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003314 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08003315 }
3316 }
3317
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003318 int dup_stdout_fd;
3319 int dup_stderr_fd;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003320 // Redirect stderr to log_path_ for debugging.
3321 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
3322 if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
3323 return ERROR;
3324 }
3325 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
3326 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
3327 strerror(errno));
3328 }
Nandana Dutt979388e2018-11-30 16:48:55 +00003329
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003330 // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
3331 // moved into zip file later, if zipping.
3332 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
3333 // TODO: why not write to a file instead of stdout to overcome this problem?
3334 /* TODO: rather than generating a text file now and zipping it later,
3335 it would be more efficient to redirect stdout to the zip entry
3336 directly, but the libziparchive doesn't support that option yet. */
3337 if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
3338 return ERROR;
3339 }
3340 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
3341 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
3342 tmp_path_.c_str(), strerror(errno));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003343 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08003344
3345 // Don't buffer stdout
3346 setvbuf(stdout, nullptr, _IONBF, 0);
3347
Rhed Jao5377d792020-07-16 17:37:39 +08003348 // Enable the parallel run if the client requests to output to a file.
3349 EnableParallelRunIfNeeded();
3350 // Using scope guard to make sure the dump pool can be shut down correctly.
3351 auto scope_guard_to_shutdown_pool = android::base::make_scope_guard([=]() {
3352 ShutdownDumpPool();
3353 });
3354
Felipe Leme608385d2016-02-01 10:35:38 -08003355 // NOTE: there should be no stdout output until now, otherwise it would break the header.
3356 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08003357 // duration is logged into MYLOG instead.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003358 PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003359
Kean Mariottica20f2d2023-12-15 09:34:25 +00003360 std::future<std::string> snapshot_system_trace;
3361
Kean Mariotti853b73a2023-07-27 12:40:30 +00003362 bool is_dumpstate_restricted =
3363 options_->telephony_only || options_->wifi_only || options_->limited_only;
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003364 if (!is_dumpstate_restricted) {
3365 // Snapshot the system trace now (if running) to avoid that dumpstate's
3366 // own activity pushes out interesting data from the trace ring buffer.
3367 // The trace file is added to the zip by MaybeAddSystemTraceToZip().
Kean Mariottica20f2d2023-12-15 09:34:25 +00003368 snapshot_system_trace = MaybeSnapshotSystemTraceAsync();
Yohei Yukawa95305b32021-03-09 07:54:27 -08003369
Kean Mariotti853b73a2023-07-27 12:40:30 +00003370 // Invoke critical dumpsys to preserve system state, before doing anything else.
3371 RunDumpsysCritical();
3372
Kean Mariotti306633e2022-09-05 16:30:47 +00003373 // Snapshot the UI traces now (if running).
3374 // The trace files will be added to bugreport later.
3375 MaybeSnapshotUiTraces();
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003376 }
Kean Mariotti853b73a2023-07-27 12:40:30 +00003377
3378 MaybeTakeEarlyScreenshot();
Kean Mariottica20f2d2023-12-15 09:34:25 +00003379 MaybeWaitForSnapshotSystemTrace(std::move(snapshot_system_trace));
Gavin Corkery6968f552020-11-22 18:09:05 +00003380 onUiIntensiveBugreportDumpsFinished(calling_uid);
3381 MaybeCheckUserConsent(calling_uid, calling_package);
3382 if (options_->telephony_only) {
3383 DumpstateTelephonyOnly(calling_package);
3384 } else if (options_->wifi_only) {
3385 DumpstateWifiOnly();
3386 } else if (options_->limited_only) {
3387 DumpstateLimitedOnly();
Elis Elliott8e401ad2023-08-08 11:18:59 +00003388 } else if (options_->onboarding_only) {
3389 DumpstateOnboardingOnly();
Gavin Corkery6968f552020-11-22 18:09:05 +00003390 } else {
Nandana Dutt4be45d12018-09-26 15:04:23 +01003391 // Dump state for the default case. This also drops root.
Jichao Lie89d9c12019-11-21 19:02:51 -08003392 RunStatus s = DumpstateDefaultAfterCritical();
Nandana Dutt5c390032019-03-12 10:52:56 +00003393 if (s != RunStatus::OK) {
Nandana Duttaac6f582019-07-26 14:32:47 +01003394 if (s == RunStatus::USER_CONSENT_DENIED) {
Nandana Dutt5c390032019-03-12 10:52:56 +00003395 HandleUserConsentDenied();
3396 }
3397 return s;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08003398 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07003399 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07003400
Felipe Leme55b42a62015-11-10 17:39:08 -08003401 /* close output if needed */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003402 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003403
Abhijeet Kaure370d682019-10-01 16:49:30 +01003404 // Zip the (now complete) .tmp file within the internal directory.
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003405 ATRACE_BEGIN("FinalizeFile");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003406 FinalizeFile();
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003407 ATRACE_END();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003408
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003409 // Share the final file with the caller if the user has consented or Shell is the caller.
Nandana Duttd2f5f082019-01-18 17:13:52 +00003410 Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
Gavin Corkerya44686c2022-11-23 18:16:51 +00003411 if (CalledByApi() && !options_->is_consent_deferred) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003412 status = CopyBugreportIfUserConsented(calling_uid);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003413 if (status != Dumpstate::RunStatus::OK &&
3414 status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3415 // Do an early return if there were errors. We make an exception for consent
3416 // timing out because it's possible the user got distracted. In this case the
3417 // bugreport is not shared but made available for manual retrieval.
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003418 MYLOGI("User denied consent. Returning\n");
Nandana Duttd2f5f082019-01-18 17:13:52 +00003419 return status;
3420 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003421 if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3422 MYLOGI(
3423 "Did not receive user consent yet."
3424 " Will not copy the bugreport artifacts to caller.\n");
Abhijeet Kaur57627412019-04-17 16:00:09 +01003425 const String16 incidentcompanion("incidentcompanion");
3426 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
3427 if (ics != nullptr) {
3428 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3429 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3430 consent_callback_.get());
3431 } else {
3432 MYLOGD("Unable to cancel user consent; incidentcompanion service unavailable\n");
3433 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003434 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003435 }
3436
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003437 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003438 if (options_->do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09003439 for (int i = 0; i < 3; i++) {
3440 Vibrate(75);
3441 usleep((75 + 50) * 1000);
3442 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003443 }
3444
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003445 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
3446 progress_->GetInitialMax());
3447 progress_->Save();
3448 MYLOGI("done (id %d)\n", id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003449
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003450 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08003451
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003452 if (control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07003453 MYLOGD("Closing control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003454 close(control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07003455 }
3456
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003457 tombstone_data_.clear();
3458 anr_data_.clear();
Andy Hungd62f7e62024-01-11 15:47:52 -08003459 anr_trace_data_.clear();
Woody Lin20767a92022-11-29 15:50:24 +08003460 shutdown_checkpoints_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01003461
Nandana Duttd2f5f082019-01-18 17:13:52 +00003462 return (consent_callback_ != nullptr &&
3463 consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
3464 ? USER_CONSENT_TIMED_OUT
3465 : RunStatus::OK;
3466}
3467
Paul Chang0d2aad72020-02-13 20:04:03 +08003468void Dumpstate::MaybeTakeEarlyScreenshot() {
3469 if (!options_->do_screenshot || !do_early_screenshot_) {
3470 return;
3471 }
3472
3473 TakeScreenshot();
3474}
3475
Kean Mariottica20f2d2023-12-15 09:34:25 +00003476std::future<std::string> Dumpstate::MaybeSnapshotSystemTraceAsync() {
Kean Mariotti853b73a2023-07-27 12:40:30 +00003477 // When capturing traces via bugreport handler (BH), this function will be invoked twice:
3478 // 1) When BH invokes IDumpstate::PreDumpUiData()
3479 // 2) When BH invokes IDumpstate::startBugreport(flags = BUGREPORT_USE_PREDUMPED_UI_DATA)
3480 // In this case we don't want to re-invoke perfetto in step 2.
3481 // In all other standard invocation states, this function is invoked once
3482 // without the flag BUGREPORT_USE_PREDUMPED_UI_DATA.
Kean Mariottica20f2d2023-12-15 09:34:25 +00003483 // This function must run asynchronously to avoid delaying MaybeTakeEarlyScreenshot() in the
3484 // standard invocation states (b/316110955).
Kean Mariotti853b73a2023-07-27 12:40:30 +00003485 if (options_->use_predumped_ui_data) {
Kean Mariottica20f2d2023-12-15 09:34:25 +00003486 return {};
3487 }
3488
3489 // Create temporary file for the command's output
3490 std::string outPath = ds.bugreport_internal_dir_ + "/tmp_serialize_perfetto_trace";
3491 auto outFd = android::base::unique_fd(TEMP_FAILURE_RETRY(
3492 open(outPath.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
3493 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
3494 if (outFd < 0) {
3495 MYLOGE("Could not open %s to serialize perfetto trace.\n", outPath.c_str());
3496 return {};
Kean Mariotti853b73a2023-07-27 12:40:30 +00003497 }
3498
3499 // If a stale file exists already, remove it.
3500 unlink(SYSTEM_TRACE_SNAPSHOT);
3501
Kean Mariottica20f2d2023-12-15 09:34:25 +00003502 MYLOGI("Launching async '%s'", SERIALIZE_PERFETTO_TRACE_TASK.c_str())
3503 return std::async(
3504 std::launch::async, [this, outPath = std::move(outPath), outFd = std::move(outFd)] {
3505 // If a background system trace is happening and is marked as "suitable for
3506 // bugreport" (i.e. bugreport_score > 0 in the trace config), this command
3507 // will stop it and serialize into SYSTEM_TRACE_SNAPSHOT. In the (likely)
3508 // case that no trace is ongoing, this command is a no-op.
3509 // Note: this should not be enqueued as we need to freeze the trace before
3510 // dumpstate starts. Otherwise the trace ring buffers will contain mostly
3511 // the dumpstate's own activity which is irrelevant.
3512 RunCommand(
3513 SERIALIZE_PERFETTO_TRACE_TASK, {"perfetto", "--save-for-bugreport"},
3514 CommandOptions::WithTimeout(10).DropRoot().CloseAllFileDescriptorsOnExec().Build(),
3515 false, outFd);
3516 // MaybeAddSystemTraceToZip() will take care of copying the trace in the zip
3517 // file in the later stages.
3518
3519 return outPath;
3520 });
3521}
3522
3523void Dumpstate::MaybeWaitForSnapshotSystemTrace(std::future<std::string> task) {
3524 if (!task.valid()) {
3525 return;
3526 }
3527
3528 WaitForTask(std::move(task), SERIALIZE_PERFETTO_TRACE_TASK, STDOUT_FILENO);
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003529}
3530
Kean Mariotti306633e2022-09-05 16:30:47 +00003531void Dumpstate::MaybeSnapshotUiTraces() {
3532 if (PropertiesHelper::IsUserBuild() || options_->use_predumped_ui_data) {
3533 return;
3534 }
Hongwei Wang9ec5c252023-01-24 15:09:59 -08003535
Pablo Gamito654831c2024-02-16 16:47:48 +00003536 std::vector<std::vector<std::string>> dumpTracesForBugReportCommands = {
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003537 {"cmd", "input_method", "tracing", "save-for-bugreport"},
3538 {"cmd", "window", "tracing", "save-for-bugreport"},
3539 {"cmd", "window", "shell", "tracing", "save-for-bugreport"},
3540 };
Hongwei Wang39229132023-01-24 15:09:59 -08003541
Pablo Gamito654831c2024-02-16 16:47:48 +00003542 if (!android_tracing_perfetto_transition_tracing()) {
3543 dumpTracesForBugReportCommands.push_back({"dumpsys", "activity", "service",
3544 "SystemUIService", "WMShell", "transitions",
3545 "tracing", "save-for-bugreport"});
3546 }
3547
Pablo Gamito6929a0e2024-02-26 23:29:47 +00003548 if (!android_tracing_perfetto_protolog_tracing()) {
Pablo Gamito654831c2024-02-16 16:47:48 +00003549 dumpTracesForBugReportCommands.push_back({"dumpsys", "activity", "service",
3550 "SystemUIService", "WMShell", "protolog",
3551 "save-for-bugreport"});
3552 }
3553
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003554 for (const auto& command : dumpTracesForBugReportCommands) {
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003555 RunCommand(
3556 // Empty name because it's not intended to be classified as a bugreport section.
3557 // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003558 "", command,
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003559 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
3560 }
Kean Mariotti306633e2022-09-05 16:30:47 +00003561}
3562
3563void Dumpstate::MaybeAddUiTracesToZip() {
3564 if (PropertiesHelper::IsUserBuild()) {
3565 return;
3566 }
3567
3568 ds.AddDir(WMTRACE_DATA_DIR, false);
Yohei Yukawa95305b32021-03-09 07:54:27 -08003569}
3570
Paul Changeb4b4642020-05-28 22:05:47 +08003571void Dumpstate::onUiIntensiveBugreportDumpsFinished(int32_t calling_uid) {
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003572 if (multiuser_get_app_id(calling_uid) == AID_SHELL || !CalledByApi()) {
Paul Changc490e662020-04-11 18:14:09 +08003573 return;
3574 }
3575 if (listener_ != nullptr) {
3576 // Let listener know ui intensive bugreport dumps are finished, then it can do event
3577 // handling if required.
Paul Changeb4b4642020-05-28 22:05:47 +08003578 listener_->onUiIntensiveBugreportDumpsFinished();
Paul Changc490e662020-04-11 18:14:09 +08003579 }
3580}
3581
Jichao Lie89d9c12019-11-21 19:02:51 -08003582void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) {
Gavin Corkerya44686c2022-11-23 18:16:51 +00003583 if (multiuser_get_app_id(calling_uid) == AID_SHELL ||
3584 !CalledByApi() || options_->is_consent_deferred) {
3585 // No need to get consent for shell triggered dumpstates, or not
3586 // through bugreporting API (i.e. no fd to copy back), or when consent
3587 // is deferred.
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003588 return;
3589 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003590 consent_callback_ = new ConsentCallback();
3591 const String16 incidentcompanion("incidentcompanion");
3592 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
Jichao Lie89d9c12019-11-21 19:02:51 -08003593 android::String16 package(calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003594 if (ics != nullptr) {
3595 MYLOGD("Checking user consent via incidentcompanion service\n");
Steven Leeb573eb82022-11-29 22:31:35 +08003596 int flags = 0x1; // IncidentManager.FLAG_CONFIRMATION_DIALOG
3597 if (IsConsentlessBugreportAllowed(*options_)) {
3598 flags |= 0x2; // IncidentManager.FLAG_ALLOW_CONSENTLESS_BUGREPORT
3599 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003600 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
Steven Leeb573eb82022-11-29 22:31:35 +08003601 calling_uid, package, String16(), String16(), flags, consent_callback_.get());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003602 } else {
3603 MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
3604 }
3605}
3606
Nandana Dutt5c390032019-03-12 10:52:56 +00003607bool Dumpstate::IsUserConsentDenied() const {
3608 return ds.consent_callback_ != nullptr &&
3609 ds.consent_callback_->getResult() == UserConsentResult::DENIED;
3610}
3611
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01003612bool Dumpstate::CalledByApi() const {
3613 return ds.options_->bugreport_fd.get() != -1 ? true : false;
3614}
3615
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003616void Dumpstate::CleanupTmpFiles() {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003617 android::os::UnlinkAndLogOnError(tmp_path_);
3618 android::os::UnlinkAndLogOnError(screenshot_path_);
3619 android::os::UnlinkAndLogOnError(path_);
Gavin Corkery789d7a52021-02-24 23:52:35 +00003620 if (dump_traces_path != nullptr) {
3621 android::os::UnlinkAndLogOnError(dump_traces_path);
3622 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003623}
3624
Rhed Jao5377d792020-07-16 17:37:39 +08003625void Dumpstate::EnableParallelRunIfNeeded() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003626 if (!PropertiesHelper::IsParallelRun()) {
Rhed Jao5377d792020-07-16 17:37:39 +08003627 return;
3628 }
3629 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003630 zip_entry_tasks_ = std::make_unique<TaskQueue>();
Rhed Jao5377d792020-07-16 17:37:39 +08003631}
3632
3633void Dumpstate::ShutdownDumpPool() {
3634 if (dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08003635 dump_pool_.reset();
Rhed Jao5377d792020-07-16 17:37:39 +08003636 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003637 if (zip_entry_tasks_) {
3638 zip_entry_tasks_->run(/* do_cancel = */true);
3639 zip_entry_tasks_ = nullptr;
3640 }
3641}
3642
3643void Dumpstate::EnqueueAddZipEntryAndCleanupIfNeeded(const std::string& entry_name,
3644 const std::string& entry_path) {
3645 auto func_add_zip_entry_and_cleanup = [=](bool task_cancelled) {
3646 if (!task_cancelled) {
3647 AddZipEntry(entry_name, entry_path);
3648 }
3649 android::os::UnlinkAndLogOnError(entry_path);
3650 };
3651 if (zip_entry_tasks_) {
3652 // Enqueues AddZipEntryAndCleanup function if the parallel run is enabled.
3653 zip_entry_tasks_->add(func_add_zip_entry_and_cleanup, _1);
3654 } else {
3655 // Invokes AddZipEntryAndCleanup immediately
3656 std::invoke(func_add_zip_entry_and_cleanup, /* task_cancelled = */false);
3657 }
Rhed Jao5377d792020-07-16 17:37:39 +08003658}
3659
Nandana Duttd2f5f082019-01-18 17:13:52 +00003660Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
3661 MYLOGD("User denied consent; deleting files and returning\n");
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003662 CleanupTmpFiles();
Nandana Duttd2f5f082019-01-18 17:13:52 +00003663 return USER_CONSENT_DENIED;
3664}
3665
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003666Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented(int32_t calling_uid) {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003667 // If the caller has asked to copy the bugreport over to their directory, we need explicit
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003668 // user consent (unless the caller is Shell).
3669 UserConsentResult consent_result;
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003670 if (multiuser_get_app_id(calling_uid) == AID_SHELL) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003671 consent_result = UserConsentResult::APPROVED;
3672 } else {
3673 consent_result = consent_callback_->getResult();
3674 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003675 if (consent_result == UserConsentResult::UNAVAILABLE) {
3676 // User has not responded yet.
3677 uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
Hunter Knepshield70610fa2020-01-03 15:27:33 -08003678 // Telephony is a fast report type, particularly on user builds where information may be
3679 // more aggressively limited. To give the user time to read the consent dialog, increase the
3680 // timeout.
3681 uint64_t timeout_ms = options_->telephony_only ? TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS
3682 : USER_CONSENT_TIMEOUT_MS;
3683 if (elapsed_ms < timeout_ms) {
3684 uint delay_seconds = (timeout_ms - elapsed_ms) / 1000;
Nandana Duttd2f5f082019-01-18 17:13:52 +00003685 MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
3686 sleep(delay_seconds);
3687 }
3688 consent_result = consent_callback_->getResult();
3689 }
3690 if (consent_result == UserConsentResult::DENIED) {
3691 // User has explicitly denied sharing with the app. To be safe delete the
3692 // internal bugreport & tmp files.
3693 return HandleUserConsentDenied();
3694 }
3695 if (consent_result == UserConsentResult::APPROVED) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00003696 bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
3697 if (copy_succeeded) {
3698 android::os::UnlinkAndLogOnError(path_);
Abhijeet Kaur9ce94672020-04-01 17:22:36 +01003699 if (options_->do_screenshot &&
3700 options_->screenshot_fd.get() != -1 &&
3701 !options_->is_screenshot_copied) {
3702 copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
3703 options_->screenshot_fd.get());
3704 options_->is_screenshot_copied = copy_succeeded;
3705 if (copy_succeeded) {
3706 android::os::UnlinkAndLogOnError(screenshot_path_);
3707 }
3708 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003709 }
3710 return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
3711 } else if (consent_result == UserConsentResult::UNAVAILABLE) {
3712 // consent_result is still UNAVAILABLE. The user has likely not responded yet.
3713 // Since we do not have user consent to share the bugreport it does not get
3714 // copied over to the calling app but remains in the internal directory from
3715 // where the user can manually pull it.
Paul Changce644212021-05-11 16:06:45 +08003716 std::string final_path = GetPath(".zip");
3717 bool copy_succeeded = android::os::CopyFileToFile(path_, final_path);
3718 if (copy_succeeded) {
3719 android::os::UnlinkAndLogOnError(path_);
3720 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003721 return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
3722 }
3723 // Unknown result; must be a programming error.
3724 MYLOGE("Unknown user consent result:%d\n", consent_result);
3725 return Dumpstate::RunStatus::ERROR;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003726}
3727
Nandana Duttf02564e2019-02-15 15:24:24 +00003728Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003729 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
3730 Dumpstate::RunStatus status = options->Initialize(argc, argv);
3731 if (status == Dumpstate::RunStatus::OK) {
Nandana Duttf02564e2019-02-15 15:24:24 +00003732 SetOptions(std::move(options));
Nandana Duttd2f5f082019-01-18 17:13:52 +00003733 // When directly running dumpstate binary, the output is not expected to be written
3734 // to any external file descriptor.
Nandana Duttf02564e2019-02-15 15:24:24 +00003735 assert(options_->bugreport_fd.get() == -1);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003736
3737 // calling_uid and calling_package are for user consent to share the bugreport with
Abhijeet Kaura407fb82020-03-27 12:51:12 +00003738 // an app; they are irrelevant here because bugreport is triggered via command line.
3739 // Update Last ID before calling Run().
3740 Initialize();
Nikhil Kumarb70622a2023-06-15 15:37:19 +01003741 status = Run(0 /* calling_uid */, "" /* calling_package */);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003742 }
Nandana Duttf02564e2019-02-15 15:24:24 +00003743 return status;
3744}
3745
3746/* Main entry point for dumpstate binary. */
3747int run_main(int argc, char* argv[]) {
3748 Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003749
3750 switch (status) {
3751 case Dumpstate::RunStatus::OK:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003752 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003753 case Dumpstate::RunStatus::HELP:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003754 ShowUsage();
3755 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003756 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003757 fprintf(stderr, "Invalid combination of args\n");
3758 ShowUsage();
3759 exit(1);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003760 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003761 FALLTHROUGH_INTENDED;
3762 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3763 FALLTHROUGH_INTENDED;
3764 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003765 exit(2);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003766 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003767}
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003768
3769// TODO(111441001): Default DumpOptions to sensible values.
3770Dumpstate::Dumpstate(const std::string& version)
3771 : pid_(getpid()),
3772 options_(new Dumpstate::DumpOptions()),
Nandana Dutt402a8392019-06-14 14:25:13 +01003773 last_reported_percent_progress_(0),
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003774 version_(version),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003775 now_(time(nullptr)),
3776 open_socket_fn_(open_socket) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003777}
3778
3779Dumpstate& Dumpstate::GetInstance() {
3780 static Dumpstate singleton_(android::base::GetProperty("dumpstate.version", VERSION_CURRENT));
3781 return singleton_;
3782}
3783
Rhed Jao5377d792020-07-16 17:37:39 +08003784DurationReporter::DurationReporter(const std::string& title, bool logcat_only, bool verbose,
3785 int duration_fd) : title_(title), logcat_only_(logcat_only), verbose_(verbose),
3786 duration_fd_(duration_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003787 if (!title_.empty()) {
3788 started_ = Nanotime();
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003789 if (title_.find("SHOW MAP") == std::string::npos) {
3790 ATRACE_ASYNC_BEGIN(title_.c_str(), 0);
3791 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003792 }
3793}
3794
3795DurationReporter::~DurationReporter() {
3796 if (!title_.empty()) {
3797 float elapsed = (float)(Nanotime() - started_) / NANOS_PER_SEC;
chenqiwuaf8b2d92019-12-12 18:53:51 +08003798 if (elapsed >= .5f || verbose_) {
3799 MYLOGD("Duration of '%s': %.2fs\n", title_.c_str(), elapsed);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003800 }
chenqiwuaf8b2d92019-12-12 18:53:51 +08003801 if (!logcat_only_) {
3802 // Use "Yoda grammar" to make it easier to grep|sort sections.
Rhed Jao5377d792020-07-16 17:37:39 +08003803 dprintf(duration_fd_, "------ %.3fs was the duration of '%s' ------\n",
3804 elapsed, title_.c_str());
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003805 }
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003806 if (title_.find("SHOW MAP") == std::string::npos) {
3807 ATRACE_ASYNC_END(title_.c_str(), 0);
3808 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003809 }
3810}
3811
3812const int32_t Progress::kDefaultMax = 5000;
3813
3814Progress::Progress(const std::string& path) : Progress(Progress::kDefaultMax, 1.1, path) {
3815}
3816
3817Progress::Progress(int32_t initial_max, int32_t progress, float growth_factor)
3818 : Progress(initial_max, growth_factor, "") {
3819 progress_ = progress;
3820}
3821
3822Progress::Progress(int32_t initial_max, float growth_factor, const std::string& path)
3823 : initial_max_(initial_max),
3824 progress_(0),
3825 max_(initial_max),
3826 growth_factor_(growth_factor),
3827 n_runs_(0),
3828 average_max_(0),
3829 path_(path) {
3830 if (!path_.empty()) {
3831 Load();
3832 }
3833}
3834
3835void Progress::Load() {
3836 MYLOGD("Loading stats from %s\n", path_.c_str());
3837 std::string content;
3838 if (!android::base::ReadFileToString(path_, &content)) {
3839 MYLOGI("Could not read stats from %s; using max of %d\n", path_.c_str(), max_);
3840 return;
3841 }
3842 if (content.empty()) {
3843 MYLOGE("No stats (empty file) on %s; using max of %d\n", path_.c_str(), max_);
3844 return;
3845 }
3846 std::vector<std::string> lines = android::base::Split(content, "\n");
3847
3848 if (lines.size() < 1) {
3849 MYLOGE("Invalid stats on file %s: not enough lines (%d). Using max of %d\n", path_.c_str(),
3850 (int)lines.size(), max_);
3851 return;
3852 }
3853 char* ptr;
3854 n_runs_ = strtol(lines[0].c_str(), &ptr, 10);
3855 average_max_ = strtol(ptr, nullptr, 10);
3856 if (n_runs_ <= 0 || average_max_ <= 0 || n_runs_ > STATS_MAX_N_RUNS ||
3857 average_max_ > STATS_MAX_AVERAGE) {
3858 MYLOGE("Invalid stats line on file %s: %s\n", path_.c_str(), lines[0].c_str());
3859 initial_max_ = Progress::kDefaultMax;
3860 } else {
3861 initial_max_ = average_max_;
3862 }
3863 max_ = initial_max_;
3864
3865 MYLOGI("Average max progress: %d in %d runs; estimated max: %d\n", average_max_, n_runs_, max_);
3866}
3867
3868void Progress::Save() {
3869 int32_t total = n_runs_ * average_max_ + progress_;
3870 int32_t runs = n_runs_ + 1;
3871 int32_t average = floor(((float)total) / runs);
3872 MYLOGI("Saving stats (total=%d, runs=%d, average=%d) on %s\n", total, runs, average,
3873 path_.c_str());
3874 if (path_.empty()) {
3875 return;
3876 }
3877
3878 std::string content = android::base::StringPrintf("%d %d\n", runs, average);
3879 if (!android::base::WriteStringToFile(content, path_)) {
3880 MYLOGE("Could not save stats on %s\n", path_.c_str());
3881 }
3882}
3883
3884int32_t Progress::Get() const {
3885 return progress_;
3886}
3887
3888bool Progress::Inc(int32_t delta_sec) {
3889 bool changed = false;
3890 if (delta_sec >= 0) {
3891 progress_ += delta_sec;
3892 if (progress_ > max_) {
3893 int32_t old_max = max_;
3894 max_ = floor((float)progress_ * growth_factor_);
3895 MYLOGD("Adjusting max progress from %d to %d\n", old_max, max_);
3896 changed = true;
3897 }
3898 }
3899 return changed;
3900}
3901
3902int32_t Progress::GetMax() const {
3903 return max_;
3904}
3905
3906int32_t Progress::GetInitialMax() const {
3907 return initial_max_;
3908}
3909
3910void Progress::Dump(int fd, const std::string& prefix) const {
3911 const char* pr = prefix.c_str();
3912 dprintf(fd, "%sprogress: %d\n", pr, progress_);
3913 dprintf(fd, "%smax: %d\n", pr, max_);
3914 dprintf(fd, "%sinitial_max: %d\n", pr, initial_max_);
3915 dprintf(fd, "%sgrowth_factor: %0.2f\n", pr, growth_factor_);
3916 dprintf(fd, "%spath: %s\n", pr, path_.c_str());
3917 dprintf(fd, "%sn_runs: %d\n", pr, n_runs_);
3918 dprintf(fd, "%saverage_max: %d\n", pr, average_max_);
3919}
3920
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003921std::string Dumpstate::GetPath(const std::string& suffix) const {
3922 return GetPath(bugreport_internal_dir_, suffix);
3923}
3924
3925std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
3926 return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
3927 name_.c_str(), suffix.c_str());
3928}
3929
3930void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
3931 progress_ = std::move(progress);
3932}
3933
3934void for_each_userid(void (*func)(int), const char *header) {
3935 std::string title = header == nullptr ? "for_each_userid" : android::base::StringPrintf(
3936 "for_each_userid(%s)", header);
3937 DurationReporter duration_reporter(title);
3938 if (PropertiesHelper::IsDryRun()) return;
3939
3940 DIR *d;
3941 struct dirent *de;
3942
3943 if (header) printf("\n------ %s ------\n", header);
3944 func(0);
3945
3946 if (!(d = opendir("/data/system/users"))) {
3947 printf("Failed to open /data/system/users (%s)\n", strerror(errno));
3948 return;
3949 }
3950
3951 while ((de = readdir(d))) {
3952 int userid;
3953 if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
3954 continue;
3955 }
3956 func(userid);
3957 }
3958
3959 closedir(d);
3960}
3961
3962static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
3963 DIR *d;
3964 struct dirent *de;
3965
3966 if (!(d = opendir("/proc"))) {
3967 printf("Failed to open /proc (%s)\n", strerror(errno));
3968 return;
3969 }
3970
3971 if (header) printf("\n------ %s ------\n", header);
3972 while ((de = readdir(d))) {
3973 if (ds.IsUserConsentDenied()) {
3974 MYLOGE(
3975 "Returning early because user denied consent to share bugreport with calling app.");
3976 closedir(d);
3977 return;
3978 }
3979 int pid;
3980 int fd;
3981 char cmdpath[255];
3982 char cmdline[255];
3983
3984 if (!(pid = atoi(de->d_name))) {
3985 continue;
3986 }
3987
3988 memset(cmdline, 0, sizeof(cmdline));
3989
3990 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
3991 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3992 TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
3993 close(fd);
3994 if (cmdline[0]) {
3995 helper(pid, cmdline, arg);
3996 continue;
3997 }
3998 }
3999
4000 // if no cmdline, a kernel thread has comm
4001 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
4002 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
4003 TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
4004 close(fd);
4005 if (cmdline[1]) {
4006 cmdline[0] = '[';
4007 size_t len = strcspn(cmdline, "\f\b\r\n");
4008 cmdline[len] = ']';
4009 cmdline[len+1] = '\0';
4010 }
4011 }
4012 if (!cmdline[0]) {
4013 strcpy(cmdline, "N/A");
4014 }
4015 helper(pid, cmdline, arg);
4016 }
4017
4018 closedir(d);
4019}
4020
4021static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
4022 for_each_pid_func *func = (for_each_pid_func*) arg;
4023 func(pid, cmdline);
4024}
4025
4026void for_each_pid(for_each_pid_func func, const char *header) {
4027 std::string title = header == nullptr ? "for_each_pid"
4028 : android::base::StringPrintf("for_each_pid(%s)", header);
4029 DurationReporter duration_reporter(title);
4030 if (PropertiesHelper::IsDryRun()) return;
4031
4032 __for_each_pid(for_each_pid_helper, header, (void *) func);
4033}
4034
4035static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
4036 DIR *d;
4037 struct dirent *de;
4038 char taskpath[255];
4039 for_each_tid_func *func = (for_each_tid_func *) arg;
4040
4041 snprintf(taskpath, sizeof(taskpath), "/proc/%d/task", pid);
4042
4043 if (!(d = opendir(taskpath))) {
4044 printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
4045 return;
4046 }
4047
4048 func(pid, pid, cmdline);
4049
4050 while ((de = readdir(d))) {
4051 if (ds.IsUserConsentDenied()) {
4052 MYLOGE(
4053 "Returning early because user denied consent to share bugreport with calling app.");
4054 closedir(d);
4055 return;
4056 }
4057 int tid;
4058 int fd;
4059 char commpath[255];
4060 char comm[255];
4061
4062 if (!(tid = atoi(de->d_name))) {
4063 continue;
4064 }
4065
4066 if (tid == pid)
4067 continue;
4068
4069 snprintf(commpath, sizeof(commpath), "/proc/%d/comm", tid);
4070 memset(comm, 0, sizeof(comm));
4071 if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
4072 strcpy(comm, "N/A");
4073 } else {
4074 char *c;
4075 TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
4076 close(fd);
4077
4078 c = strrchr(comm, '\n');
4079 if (c) {
4080 *c = '\0';
4081 }
4082 }
4083 func(pid, tid, comm);
4084 }
4085
4086 closedir(d);
4087}
4088
4089void for_each_tid(for_each_tid_func func, const char *header) {
4090 std::string title = header == nullptr ? "for_each_tid"
4091 : android::base::StringPrintf("for_each_tid(%s)", header);
4092 DurationReporter duration_reporter(title);
4093
4094 if (PropertiesHelper::IsDryRun()) return;
4095
4096 __for_each_pid(for_each_tid_helper, header, (void *) func);
4097}
4098
4099void show_wchan(int pid, int tid, const char *name) {
4100 if (PropertiesHelper::IsDryRun()) return;
4101
4102 char path[255];
4103 char buffer[255];
4104 int fd, ret, save_errno;
4105 char name_buffer[255];
4106
4107 memset(buffer, 0, sizeof(buffer));
4108
4109 snprintf(path, sizeof(path), "/proc/%d/wchan", tid);
4110 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
4111 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
4112 return;
4113 }
4114
4115 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
4116 save_errno = errno;
4117 close(fd);
4118
4119 if (ret < 0) {
4120 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
4121 return;
4122 }
4123
4124 snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
4125 pid == tid ? 0 : 3, "", name);
4126
4127 printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
4128
4129 return;
4130}
4131
4132// print time in centiseconds
4133static void snprcent(char *buffer, size_t len, size_t spc,
4134 unsigned long long time) {
4135 static long hz; // cache discovered hz
4136
4137 if (hz <= 0) {
4138 hz = sysconf(_SC_CLK_TCK);
4139 if (hz <= 0) {
4140 hz = 1000;
4141 }
4142 }
4143
4144 // convert to centiseconds
4145 time = (time * 100 + (hz / 2)) / hz;
4146
4147 char str[16];
4148
4149 snprintf(str, sizeof(str), " %llu.%02u",
4150 time / 100, (unsigned)(time % 100));
4151 size_t offset = strlen(buffer);
4152 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
4153 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
4154}
4155
4156// print permille as a percent
4157static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
4158 char str[16];
4159
4160 snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
4161 size_t offset = strlen(buffer);
4162 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
4163 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
4164}
4165
4166void show_showtime(int pid, const char *name) {
4167 if (PropertiesHelper::IsDryRun()) return;
4168
4169 char path[255];
4170 char buffer[1023];
4171 int fd, ret, save_errno;
4172
4173 memset(buffer, 0, sizeof(buffer));
4174
4175 snprintf(path, sizeof(path), "/proc/%d/stat", pid);
4176 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
4177 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
4178 return;
4179 }
4180
4181 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
4182 save_errno = errno;
4183 close(fd);
4184
4185 if (ret < 0) {
4186 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
4187 return;
4188 }
4189
4190 // field 14 is utime
4191 // field 15 is stime
4192 // field 42 is iotime
4193 unsigned long long utime = 0, stime = 0, iotime = 0;
4194 if (sscanf(buffer,
4195 "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
4196 "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
4197 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
4198 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
4199 &utime, &stime, &iotime) != 3) {
4200 return;
4201 }
4202
4203 unsigned long long total = utime + stime;
4204 if (!total) {
4205 return;
4206 }
4207
4208 unsigned permille = (iotime * 1000 + (total / 2)) / total;
4209 if (permille > 1000) {
4210 permille = 1000;
4211 }
4212
4213 // try to beautify and stabilize columns at <80 characters
4214 snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
4215 if ((name[0] != '[') || utime) {
4216 snprcent(buffer, sizeof(buffer), 57, utime);
4217 }
4218 snprcent(buffer, sizeof(buffer), 65, stime);
4219 if ((name[0] != '[') || iotime) {
4220 snprcent(buffer, sizeof(buffer), 73, iotime);
4221 }
4222 if (iotime) {
4223 snprdec(buffer, sizeof(buffer), 79, permille);
4224 }
4225 puts(buffer); // adds a trailing newline
4226
4227 return;
4228}
4229
4230void do_dmesg() {
4231 const char *title = "KERNEL LOG (dmesg)";
4232 DurationReporter duration_reporter(title);
4233 printf("------ %s ------\n", title);
4234
4235 if (PropertiesHelper::IsDryRun()) return;
4236
4237 /* Get size of kernel buffer */
4238 int size = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
4239 if (size <= 0) {
4240 printf("Unexpected klogctl return value: %d\n\n", size);
4241 return;
4242 }
4243 char *buf = (char *) malloc(size + 1);
4244 if (buf == nullptr) {
4245 printf("memory allocation failed\n\n");
4246 return;
4247 }
4248 int retval = klogctl(KLOG_READ_ALL, buf, size);
4249 if (retval < 0) {
4250 printf("klogctl failure\n\n");
4251 free(buf);
4252 return;
4253 }
4254 buf[retval] = '\0';
4255 printf("%s\n\n", buf);
4256 free(buf);
4257 return;
4258}
4259
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004260int Dumpstate::DumpFile(const std::string& title, const std::string& path) {
4261 DurationReporter duration_reporter(title);
4262
4263 int status = DumpFileToFd(STDOUT_FILENO, title, path);
4264
4265 UpdateProgress(WEIGHT_FILE);
4266
4267 return status;
4268}
4269
4270int read_file_as_long(const char *path, long int *output) {
luoqiangwei15fcf2022024-03-07 15:29:20 +08004271 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
4272 if (fd.get() < 0) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004273 int err = errno;
4274 MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
4275 return -1;
4276 }
4277 char buffer[50];
luoqiangwei15fcf2022024-03-07 15:29:20 +08004278 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer, sizeof(buffer)));
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004279 if (bytes_read == -1) {
4280 MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
4281 return -2;
4282 }
4283 if (bytes_read == 0) {
4284 MYLOGE("File %s is empty\n", path);
4285 return -3;
4286 }
4287 *output = atoi(buffer);
4288 return 0;
4289}
4290
4291/* calls skip to gate calling dump_from_fd recursively
4292 * in the specified directory. dump_from_fd defaults to
4293 * dump_file_from_fd above when set to NULL. skip defaults
4294 * to false when set to NULL. dump_from_fd will always be
4295 * called with title NULL.
4296 */
4297int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
4298 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4299 DurationReporter duration_reporter(title);
4300 DIR *dirp;
4301 struct dirent *d;
4302 char *newpath = nullptr;
4303 const char *slash = "/";
4304 int retval = 0;
4305
4306 if (!title.empty()) {
4307 printf("------ %s (%s) ------\n", title.c_str(), dir);
4308 }
4309 if (PropertiesHelper::IsDryRun()) return 0;
4310
4311 if (dir[strlen(dir) - 1] == '/') {
4312 ++slash;
4313 }
4314 dirp = opendir(dir);
4315 if (dirp == nullptr) {
4316 retval = -errno;
4317 MYLOGE("%s: %s\n", dir, strerror(errno));
4318 return retval;
4319 }
4320
4321 if (!dump_from_fd) {
4322 dump_from_fd = dump_file_from_fd;
4323 }
4324 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4325 if ((d->d_name[0] == '.')
4326 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4327 || (d->d_name[1] == '\0'))) {
4328 continue;
4329 }
4330 asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
4331 (d->d_type == DT_DIR) ? "/" : "");
4332 if (!newpath) {
4333 retval = -errno;
4334 continue;
4335 }
4336 if (skip && (*skip)(newpath)) {
4337 continue;
4338 }
4339 if (d->d_type == DT_DIR) {
4340 int ret = dump_files("", newpath, skip, dump_from_fd);
4341 if (ret < 0) {
4342 retval = ret;
4343 }
4344 continue;
4345 }
4346 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
4347 if (fd.get() < 0) {
4348 retval = -1;
4349 printf("*** %s: %s\n", newpath, strerror(errno));
4350 continue;
4351 }
4352 (*dump_from_fd)(nullptr, newpath, fd.get());
4353 }
4354 closedir(dirp);
4355 if (!title.empty()) {
4356 printf("\n");
4357 }
4358 return retval;
4359}
4360
4361/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
4362 * it's possible to avoid issues where opening the file itself can get
4363 * stuck.
4364 */
4365int dump_file_from_fd(const char *title, const char *path, int fd) {
4366 if (PropertiesHelper::IsDryRun()) return 0;
4367
4368 int flags = fcntl(fd, F_GETFL);
4369 if (flags == -1) {
4370 printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
4371 return -1;
4372 } else if (!(flags & O_NONBLOCK)) {
4373 printf("*** %s: fd must have O_NONBLOCK set.\n", path);
4374 return -1;
4375 }
4376 return DumpFileFromFdToFd(title, path, fd, STDOUT_FILENO, PropertiesHelper::IsDryRun());
4377}
4378
4379int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004380 const CommandOptions& options, bool verbose_duration, int out_fd) {
4381 DurationReporter duration_reporter(title, false /* logcat_only */,
4382 verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004383
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004384 int status = RunCommandToFd(out_fd, title, full_command, options);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004385
4386 /* TODO: for now we're simplifying the progress calculation by using the
4387 * timeout as the weight. It's a good approximation for most cases, except when calling dumpsys,
4388 * where its weight should be much higher proportionally to its timeout.
4389 * Ideally, it should use a options.EstimatedDuration() instead...*/
4390 UpdateProgress(options.Timeout());
4391
4392 return status;
4393}
4394
4395void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
Rhed Jaoe017f982020-07-21 17:58:41 +08004396 const CommandOptions& options, long dumpsysTimeoutMs, int out_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004397 long timeout_ms = dumpsysTimeoutMs > 0 ? dumpsysTimeoutMs : options.TimeoutInMs();
4398 std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-T", std::to_string(timeout_ms)};
4399 dumpsys.insert(dumpsys.end(), dumpsys_args.begin(), dumpsys_args.end());
Rhed Jaoe017f982020-07-21 17:58:41 +08004400 RunCommand(title, dumpsys, options, false, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004401}
4402
Dieter Hsu105ad0c2020-09-29 15:23:33 +08004403static int open_socket(const char* service) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004404 int s = android_get_control_socket(service);
4405 if (s < 0) {
4406 MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
4407 return -1;
4408 }
4409 fcntl(s, F_SETFD, FD_CLOEXEC);
4410
4411 // Set backlog to 0 to make sure that queue size will be minimum.
4412 // In Linux, because the minimum queue will be 1, connect() will be blocked
4413 // if the other clients already called connect() and the connection request was not accepted.
4414 if (listen(s, 0) < 0) {
4415 MYLOGE("listen(control socket): %s\n", strerror(errno));
4416 return -1;
4417 }
4418
4419 struct sockaddr addr;
4420 socklen_t alen = sizeof(addr);
Abhijeet Kaur2113cae2019-09-13 09:24:15 +01004421 int fd = accept4(s, &addr, &alen, SOCK_CLOEXEC);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004422
4423 // Close socket just after accept(), to make sure that connect() by client will get error
4424 // when the socket is used by the other services.
4425 // There is still a race condition possibility between accept and close, but there is no way
4426 // to close-on-accept atomically.
4427 // See detail; b/123306389#comment25
4428 close(s);
4429
4430 if (fd < 0) {
4431 MYLOGE("accept(control socket): %s\n", strerror(errno));
4432 return -1;
4433 }
4434
4435 return fd;
4436}
4437
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004438// TODO: should call is_valid_output_file and/or be merged into it.
4439void create_parent_dirs(const char *path) {
4440 char *chp = const_cast<char *> (path);
4441
4442 /* skip initial slash */
4443 if (chp[0] == '/')
4444 chp++;
4445
4446 /* create leading directories, if necessary */
4447 struct stat dir_stat;
4448 while (chp && chp[0]) {
4449 chp = strchr(chp, '/');
4450 if (chp) {
4451 *chp = 0;
4452 if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
4453 MYLOGI("Creating directory %s\n", path);
4454 if (mkdir(path, 0770)) { /* drwxrwx--- */
4455 MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
4456 } else if (chown(path, AID_SHELL, AID_SHELL)) {
4457 MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
4458 }
4459 }
4460 *chp++ = '/';
4461 }
4462 }
4463}
4464
4465bool _redirect_to_file(FILE* redirect, char* path, int truncate_flag) {
4466 create_parent_dirs(path);
4467
4468 int fd = TEMP_FAILURE_RETRY(open(path,
4469 O_WRONLY | O_CREAT | truncate_flag | O_CLOEXEC | O_NOFOLLOW,
4470 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
4471 if (fd < 0) {
4472 MYLOGE("%s: %s\n", path, strerror(errno));
4473 return false;
4474 }
4475
4476 TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
4477 close(fd);
4478 return true;
4479}
4480
4481bool redirect_to_file(FILE* redirect, char* path) {
4482 return _redirect_to_file(redirect, path, O_TRUNC);
4483}
4484
4485bool redirect_to_existing_file(FILE* redirect, char* path) {
4486 return _redirect_to_file(redirect, path, O_APPEND);
4487}
4488
4489void dump_route_tables() {
4490 DurationReporter duration_reporter("DUMP ROUTE TABLES");
4491 if (PropertiesHelper::IsDryRun()) return;
4492 const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
4493 ds.DumpFile("RT_TABLES", RT_TABLES_PATH);
4494 FILE* fp = fopen(RT_TABLES_PATH, "re");
4495 if (!fp) {
4496 printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
4497 return;
4498 }
4499 char table[16];
4500 // Each line has an integer (the table number), a space, and a string (the table name). We only
4501 // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
4502 // Add a fixed max limit so this doesn't go awry.
4503 for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
4504 RunCommand("ROUTE TABLE IPv4", {"ip", "-4", "route", "show", "table", table});
4505 RunCommand("ROUTE TABLE IPv6", {"ip", "-6", "route", "show", "table", table});
4506 }
4507 fclose(fp);
4508}
4509
Li Li830179f2022-01-04 12:53:29 -08004510void dump_frozen_cgroupfs(const char *dir, int level,
4511 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4512 DIR *dirp;
4513 struct dirent *d;
4514 char *newpath = nullptr;
4515
4516 dirp = opendir(dir);
4517 if (dirp == nullptr) {
4518 MYLOGE("%s: %s\n", dir, strerror(errno));
4519 return;
4520 }
4521
4522 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4523 if ((d->d_name[0] == '.')
4524 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4525 || (d->d_name[1] == '\0'))) {
4526 continue;
4527 }
4528 if (d->d_type == DT_DIR) {
4529 asprintf(&newpath, "%s/%s/", dir, d->d_name);
4530 if (!newpath) {
4531 continue;
4532 }
4533 if (level == 0 && !strncmp(d->d_name, "uid_", 4)) {
4534 dump_frozen_cgroupfs(newpath, 1, dump_from_fd);
4535 } else if (level == 1 && !strncmp(d->d_name, "pid_", 4)) {
4536 char *freezer = nullptr;
4537 asprintf(&freezer, "%s/%s", newpath, "cgroup.freeze");
4538 if (freezer) {
4539 FILE* fp = fopen(freezer, "r");
4540 if (fp != NULL) {
4541 int frozen;
4542 fscanf(fp, "%d", &frozen);
4543 if (frozen > 0) {
4544 dump_files("", newpath, skip_none, dump_from_fd);
4545 }
4546 fclose(fp);
4547 }
4548 free(freezer);
4549 }
4550 }
4551 }
4552 }
4553 closedir(dirp);
4554}
4555
4556void dump_frozen_cgroupfs() {
Li Li830179f2022-01-04 12:53:29 -08004557 MYLOGD("Adding frozen processes from %s\n", CGROUPFS_DIR);
4558 DurationReporter duration_reporter("FROZEN CGROUPFS");
4559 if (PropertiesHelper::IsDryRun()) return;
4560 dump_frozen_cgroupfs(CGROUPFS_DIR, 0, _add_file_from_fd);
4561}
4562
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004563void Dumpstate::UpdateProgress(int32_t delta_sec) {
4564 if (progress_ == nullptr) {
4565 MYLOGE("UpdateProgress: progress_ not set\n");
4566 return;
4567 }
Rhed Jaobf63d8a2020-07-21 15:42:55 +08004568 // This function updates progress related members of the dumpstate and reports
4569 // progress percentage to the bugreport client. Since it could be called by
4570 // different dump tasks at the same time if the parallel run is enabled, a
4571 // mutex lock is necessary here to synchronize the call.
4572 std::lock_guard<std::recursive_mutex> lock(mutex_);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004573
4574 // Always update progess so stats can be tuned...
Nandana Dutt402a8392019-06-14 14:25:13 +01004575 progress_->Inc(delta_sec);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004576
4577 // ...but only notifiy listeners when necessary.
4578 if (!options_->do_progress_updates) return;
4579
4580 int progress = progress_->Get();
4581 int max = progress_->GetMax();
Nandana Dutt402a8392019-06-14 14:25:13 +01004582 int percent = 100 * progress / max;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004583
Nandana Dutt402a8392019-06-14 14:25:13 +01004584 if (last_reported_percent_progress_ > 0 && percent <= last_reported_percent_progress_) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004585 return;
4586 }
Nandana Dutt402a8392019-06-14 14:25:13 +01004587 last_reported_percent_progress_ = percent;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004588
4589 if (control_socket_fd_ >= 0) {
4590 dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
4591 fsync(control_socket_fd_);
4592 }
4593
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004594 if (listener_ != nullptr) {
Nandana Dutt235c6672019-11-14 15:22:32 +00004595 if (percent % 10 == 0) {
4596 // We don't want to spam logcat, so only log multiples of 10.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004597 MYLOGD("Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004598 } else {
4599 // stderr is ignored on normal invocations, but useful when calling
4600 // /system/bin/dumpstate directly for debuggging.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004601 fprintf(stderr, "Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004602 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004603
4604 listener_->onProgress(percent);
4605 }
4606}
4607
4608void Dumpstate::TakeScreenshot(const std::string& path) {
4609 const std::string& real_path = path.empty() ? screenshot_path_ : path;
4610 int status =
Abdelrahman Daim30e23602024-08-20 02:19:37 -07004611 RunCommand("", {"screencap", "-p", real_path},
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004612 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
4613 if (status == 0) {
4614 MYLOGD("Screenshot saved on %s\n", real_path.c_str());
4615 } else {
4616 MYLOGE("Failed to take screenshot on %s\n", real_path.c_str());
4617 }
Paul Chang0d2aad72020-02-13 20:04:03 +08004618 if (listener_ != nullptr) {
4619 // Show a visual indication to indicate screenshot is taken via
4620 // IDumpstateListener.onScreenshotTaken()
4621 listener_->onScreenshotTaken(status == 0);
4622 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004623}
4624
4625bool is_dir(const char* pathname) {
4626 struct stat info;
4627 if (stat(pathname, &info) == -1) {
4628 return false;
4629 }
4630 return S_ISDIR(info.st_mode);
4631}
4632
4633time_t get_mtime(int fd, time_t default_mtime) {
4634 struct stat info;
4635 if (fstat(fd, &info) == -1) {
4636 return default_mtime;
4637 }
4638 return info.st_mtime;
4639}