blob: 9e3e2b046849fafd71f06e74c9082455cb17250d [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>
Primiano Tucci06d34202025-02-13 11:17:06 -080060#include <perfetto_flags.h>
Pablo Gamito654831c2024-02-16 16:47:48 +000061#include <poll.h>
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070062#include <private/android_filesystem_config.h>
63#include <private/android_logger.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080064#include <serviceutils/PriorityDumper.h>
Pablo Gamito654831c2024-02-16 16:47:48 +000065#include <signal.h>
66#include <stdarg.h>
67#include <stdbool.h>
68#include <stdio.h>
69#include <stdlib.h>
70#include <string.h>
71#include <sys/capability.h>
72#include <sys/inotify.h>
73#include <sys/klog.h>
74#include <sys/mount.h>
75#include <sys/poll.h>
76#include <sys/prctl.h>
77#include <sys/resource.h>
78#include <sys/stat.h>
79#include <sys/time.h>
80#include <sys/wait.h>
81#include <time.h>
82#include <unistd.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070083#include <utils/StrongPointer.h>
Devin Moore8df81bb2022-06-08 22:47:02 +000084#include <vintf/VintfObject.h>
Pablo Gamito654831c2024-02-16 16:47:48 +000085
86#include <chrono>
87#include <cmath>
88#include <fstream>
89#include <functional>
90#include <future>
91#include <memory>
92#include <numeric>
93#include <regex>
94#include <set>
95#include <string>
96#include <utility>
97#include <vector>
98
Felipe Lemef0292972016-11-22 13:57:05 -080099#include "DumpstateInternal.h"
Felipe Leme75876a22016-10-27 16:31:27 -0700100#include "DumpstateService.h"
Felipe Leme6e01fa62015-11-11 19:35:14 -0800101
Kedar Chitnis9fd8c052021-11-16 09:09:22 +0000102namespace dumpstate_hal_hidl_1_0 = android::hardware::dumpstate::V1_0;
103namespace dumpstate_hal_hidl = android::hardware::dumpstate::V1_1;
104namespace dumpstate_hal_aidl = aidl::android::hardware::dumpstate;
105
Vishnu Naire97d6122018-01-18 13:58:56 -0800106using ::std::literals::chrono_literals::operator""ms;
107using ::std::literals::chrono_literals::operator""s;
Rhed Jao5377d792020-07-16 17:37:39 +0800108using ::std::placeholders::_1;
Steven Morelandcb7ef822016-11-29 13:20:37 -0800109
Felipe Leme47e9be22016-12-21 15:37:07 -0800110// TODO: remove once moved to namespace
Vishnu Naire97d6122018-01-18 13:58:56 -0800111using android::defaultServiceManager;
112using android::Dumpsys;
113using android::INVALID_OPERATION;
114using android::IServiceManager;
115using android::OK;
116using android::sp;
117using android::status_t;
118using android::String16;
119using android::String8;
120using android::TIMED_OUT;
121using android::UNKNOWN_ERROR;
122using android::Vector;
Nandana Dutt979388e2018-11-30 16:48:55 +0000123using android::base::StringPrintf;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000124using android::os::IDumpstateListener;
Felipe Leme47e9be22016-12-21 15:37:07 -0800125using android::os::dumpstate::CommandOptions;
126using android::os::dumpstate::DumpFileToFd;
Rhed Jao5377d792020-07-16 17:37:39 +0800127using android::os::dumpstate::DumpPool;
Vishnu Naire97d6122018-01-18 13:58:56 -0800128using android::os::dumpstate::PropertiesHelper;
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800129using android::os::dumpstate::TaskQueue;
Chris Morinbc223142022-02-04 14:17:11 -0800130using android::os::dumpstate::WaitForTask;
Felipe Leme47e9be22016-12-21 15:37:07 -0800131
Steven Moreland0d564d52025-01-10 22:24:57 +0000132// BAD - See README.md: "Dumpstate philosophy: exec not link"
133// Do not add more complicated variables here, prefer to execute only. Don't link more code here.
134
Abhijeet Kaurcf234e82019-07-01 14:53:55 +0100135// Keep in sync with
136// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
137static const int TRACE_DUMP_TIMEOUT_MS = 10000; // 10 seconds
138
139/* Most simple commands have 10 as timeout, so 5 is a good estimate */
140static const int32_t WEIGHT_FILE = 5;
141
142// TODO: temporary variables and functions used during C++ refactoring
143static Dumpstate& ds = Dumpstate::GetInstance();
144static int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Nandana Dutt8d945c02019-08-14 13:30:07 +0100145 const CommandOptions& options = CommandOptions::DEFAULT,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800146 bool verbose_duration = false, int out_fd = STDOUT_FILENO) {
147 return ds.RunCommand(title, full_command, options, verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +0100148}
149
150// Reasonable value for max stats.
151static const int STATS_MAX_N_RUNS = 1000;
152static const long STATS_MAX_AVERAGE = 100000;
153
154CommandOptions Dumpstate::DEFAULT_DUMPSYS = CommandOptions::WithTimeout(30).Build();
155
Nandana Duttd2f5f082019-01-18 17:13:52 +0000156typedef Dumpstate::ConsentCallback::ConsentResult UserConsentResult;
157
Colin Crossf45fa6b2012-03-26 12:38:26 -0700158/* read before root is shed */
159static char cmdline_buf[16384] = "(unknown)";
Yi Kong19d5c002018-07-20 13:39:55 -0700160static const char *dump_traces_path = nullptr;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000161static const uint64_t USER_CONSENT_TIMEOUT_MS = 30 * 1000;
Hunter Knepshield70610fa2020-01-03 15:27:33 -0800162// Because telephony reports are significantly faster to collect (< 10 seconds vs. > 2 minutes),
163// it's often the case that they time out far too quickly for consent with such a hefty dialog for
164// the user to read. For telephony reports only, we increase the default timeout to 2 minutes to
165// roughly match full reports' durations.
166static const uint64_t TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS = 2 * 60 * 1000;
Colin Crossf45fa6b2012-03-26 12:38:26 -0700167
Felipe Leme1d486fe2016-10-14 18:06:47 -0700168// TODO: variables and functions below should be part of dumpstate object
169
Felipe Leme635ca312016-01-05 14:23:02 -0800170static std::set<std::string> mount_points;
171void add_mountinfo();
Felipe Leme78f2c862015-12-21 09:55:22 -0800172
Todd Poynor2a83daa2013-11-22 15:44:22 -0800173#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
Mark Salyzyn7d0a7622016-06-24 14:06:15 -0700174#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
Wei Wang509bb5d2017-06-09 14:42:12 -0700175#define BLK_DEV_SYS_DIR "/sys/block"
Todd Poynor2a83daa2013-11-22 15:44:22 -0800176
Ted Bauerf6d61b82024-09-13 19:57:19 +0000177#define AFLAGS "/system/bin/aflags"
Felipe Lemee82a27d2016-01-05 13:35:44 -0800178#define RECOVERY_DIR "/cache/recovery"
Mark Salyzynd6ab0112016-03-25 12:56:39 -0700179#define RECOVERY_DATA_DIR "/data/misc/recovery"
Tianjie Xu75d53362018-04-11 16:42:28 -0700180#define UPDATE_ENGINE_LOG_DIR "/data/misc/update_engine_log"
Kelvin Zhang6eaa0f92022-09-12 09:29:19 -0700181#define UPDATE_ENGINE_PREF_DIR "/data/misc/update_engine/prefs"
Mark Salyzyn4d42dea2016-04-01 10:03:14 -0700182#define LOGPERSIST_DATA_DIR "/data/misc/logd"
Jerry Changa1df8a92020-01-02 16:03:39 +0800183#define PREREBOOT_DATA_DIR "/data/misc/prereboot"
David Brazdild2991962016-06-03 14:40:44 +0100184#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
185#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
Benedict Wong8f9d8a42019-01-03 16:19:38 -0800186#define XFRM_STAT_PROC_FILE "/proc/net/xfrm_stat"
Steven Moreland9379c462023-12-21 02:04:27 +0000187#define KERNEL_CONFIG "/proc/config.gz"
Erik Kline08165202016-05-30 11:55:44 +0900188#define WLUTIL "/vendor/xbin/wlutil"
Vishnu Nair36b4cdb2017-11-17 10:27:05 -0800189#define WMTRACE_DATA_DIR "/data/misc/wmtrace"
Yifan Hong3945e1b2019-10-29 12:59:23 -0700190#define OTA_METADATA_DIR "/metadata/ota"
Yifan Hong0efa7972020-02-03 16:45:02 -0800191#define SNAPSHOTCTL_LOG_DIR "/data/misc/snapshotctl_log"
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +0900192#define LINKERCONFIG_DIR "/linkerconfig"
Calin Juravlef84d3692020-04-28 15:31:12 -0700193#define PACKAGE_DEX_USE_LIST "/data/system/package-dex-usage.list"
Primiano Tucci06d34202025-02-13 11:17:06 -0800194#define SYSTEM_TRACE_DIR "/data/misc/perfetto-traces/bugreport"
Li Li2eedd412021-06-30 15:11:53 -0700195#define CGROUPFS_DIR "/sys/fs/cgroup"
MÃ¥rten Kongstad60195a72022-09-20 14:14:20 +0200196#define SDK_EXT_INFO "/apex/com.android.sdkext/bin/derive_sdk"
Jeff Sharkey9df29d52023-02-06 14:26:30 -0700197#define DROPBOX_DIR "/data/system/dropbox"
Nattharat Jariyanuntanaetb250cae2024-05-15 07:48:19 +0000198#define UWB_LOG_DIR "/data/misc/apexdata/com.android.uwb/log"
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700199
Narayan Kamath8f788292017-05-25 13:20:39 +0100200// TODO(narayan): Since this information has to be kept in sync
201// with tombstoned, we should just put it in a common header.
202//
203// File: system/core/debuggerd/tombstoned/tombstoned.cpp
Narayan Kamathbd863722017-06-01 18:50:12 +0100204static const std::string TOMBSTONE_DIR = "/data/tombstones/";
205static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
206static const std::string ANR_DIR = "/data/anr/";
207static const std::string ANR_FILE_PREFIX = "anr_";
Andy Hungd62f7e62024-01-11 15:47:52 -0800208static const std::string ANR_TRACE_FILE_PREFIX = "trace_";
Woody Lin20767a92022-11-29 15:50:24 +0800209static const std::string SHUTDOWN_CHECKPOINTS_DIR = "/data/system/shutdown-checkpoints/";
210static const std::string SHUTDOWN_CHECKPOINTS_FILE_PREFIX = "checkpoints-";
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700211
Kunduz Baryktabasova3a5b65a2024-10-07 11:53:48 +0000212// File path to default screenshot image, that used when failed to capture the real screenshot.
213static const std::string DEFAULT_SCREENSHOT_PATH = "/system/etc/default_screenshot.png";
214
Felipe Lemee844a9d2016-09-21 15:01:39 -0700215// TODO: temporary variables and functions used during C++ refactoring
Nandana Dutt979388e2018-11-30 16:48:55 +0000216
Nandana Dutt5c390032019-03-12 10:52:56 +0000217#define RETURN_IF_USER_DENIED_CONSENT() \
218 if (ds.IsUserConsentDenied()) { \
219 MYLOGE("Returning early as user denied consent to share bugreport with calling app."); \
220 return Dumpstate::RunStatus::USER_CONSENT_DENIED; \
221 }
222
223// Runs func_ptr, but checks user consent before and after running it. Returns USER_CONSENT_DENIED
224// if consent is found to be denied.
225#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(func_ptr, ...) \
226 RETURN_IF_USER_DENIED_CONSENT(); \
227 func_ptr(__VA_ARGS__); \
228 RETURN_IF_USER_DENIED_CONSENT();
229
Rhed Jao5377d792020-07-16 17:37:39 +0800230// Runs func_ptr, and logs a duration report after it's finished.
231#define RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, ...) \
232 { \
233 DurationReporter duration_reporter_in_macro(log_title); \
234 func_ptr(__VA_ARGS__); \
235 }
236
237// Similar with RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK, an additional duration report
238// is output after a slow function is finished.
239#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(log_title, func_ptr, ...) \
240 RETURN_IF_USER_DENIED_CONSENT(); \
241 RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, __VA_ARGS__); \
242 RETURN_IF_USER_DENIED_CONSENT();
243
Chris Morinbc223142022-02-04 14:17:11 -0800244#define WAIT_TASK_WITH_CONSENT_CHECK(future) \
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800245 RETURN_IF_USER_DENIED_CONSENT(); \
Chris Morinbc223142022-02-04 14:17:11 -0800246 WaitForTask(future); \
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800247 RETURN_IF_USER_DENIED_CONSENT();
248
Sahana Raof35ed432019-07-12 10:47:52 +0100249static const char* WAKE_LOCK_NAME = "dumpstate_wakelock";
250
Rhed Jao5377d792020-07-16 17:37:39 +0800251// Names of parallel tasks, they are used for the DumpPool to identify the dump
252// task and the log title of the duration report.
253static const std::string DUMP_TRACES_TASK = "DUMP TRACES";
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800254static const std::string DUMP_INCIDENT_REPORT_TASK = "INCIDENT REPORT";
Aaron Huang24d215d2022-04-27 18:51:16 +0800255static const std::string DUMP_NETSTATS_PROTO_TASK = "DUMP NETSTATS PROTO";
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800256static const std::string DUMP_HALS_TASK = "DUMP HALS";
257static const std::string DUMP_BOARD_TASK = "dumpstate_board()";
Rhed Jaoe017f982020-07-21 17:58:41 +0800258static const std::string DUMP_CHECKINS_TASK = "DUMP CHECKINS";
Kean Mariottica20f2d2023-12-15 09:34:25 +0000259static const std::string SERIALIZE_PERFETTO_TRACE_TASK = "SERIALIZE PERFETTO TRACE";
Rhed Jao5377d792020-07-16 17:37:39 +0800260
Nandana Dutt979388e2018-11-30 16:48:55 +0000261namespace android {
262namespace os {
263namespace {
264
265static int Open(std::string path, int flags, mode_t mode = 0) {
266 int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
267 if (fd == -1) {
268 MYLOGE("open(%s, %s)\n", path.c_str(), strerror(errno));
269 }
270 return fd;
271}
272
mhasank2d75c442020-06-11 15:05:25 -0700273static int OpenForWrite(std::string path) {
274 return Open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
275 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
276}
Nandana Dutt979388e2018-11-30 16:48:55 +0000277
278static int OpenForRead(std::string path) {
279 return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
280}
281
282bool CopyFile(int in_fd, int out_fd) {
283 char buf[4096];
284 ssize_t byte_count;
285 while ((byte_count = TEMP_FAILURE_RETRY(read(in_fd, buf, sizeof(buf)))) > 0) {
286 if (!android::base::WriteFully(out_fd, buf, byte_count)) {
287 return false;
288 }
289 }
290 return (byte_count != -1);
291}
292
293static bool CopyFileToFd(const std::string& input_file, int out_fd) {
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000294 MYLOGD("Going to copy file (%s) to %d\n", input_file.c_str(), out_fd);
Nandana Dutt979388e2018-11-30 16:48:55 +0000295
296 // Obtain a handle to the source file.
297 android::base::unique_fd in_fd(OpenForRead(input_file));
298 if (out_fd != -1 && in_fd.get() != -1) {
299 if (CopyFile(in_fd.get(), out_fd)) {
300 return true;
301 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000302 MYLOGE("Failed to copy file: %s\n", strerror(errno));
Nandana Dutt979388e2018-11-30 16:48:55 +0000303 }
304 return false;
305}
306
Nandana Duttd2f5f082019-01-18 17:13:52 +0000307static bool UnlinkAndLogOnError(const std::string& file) {
Nandana Dutt8ae16e62020-03-27 10:20:22 +0000308 if (file.empty()) {
309 return false;
310 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000311 if (unlink(file.c_str())) {
312 MYLOGE("Failed to unlink file (%s): %s\n", file.c_str(), strerror(errno));
Nandana Duttd2f5f082019-01-18 17:13:52 +0000313 return false;
314 }
315 return true;
316}
Nandana Dutt979388e2018-11-30 16:48:55 +0000317
Nikita Ioffea325a572019-05-16 19:49:47 +0100318int64_t GetModuleMetadataVersion() {
319 auto binder = defaultServiceManager()->getService(android::String16("package_native"));
320 if (binder == nullptr) {
321 MYLOGE("Failed to retrieve package_native service");
322 return 0L;
323 }
324 auto package_service = android::interface_cast<content::pm::IPackageManagerNative>(binder);
325 std::string package_name;
326 auto status = package_service->getModuleMetadataPackageName(&package_name);
327 if (!status.isOk()) {
328 MYLOGE("Failed to retrieve module metadata package name: %s", status.toString8().c_str());
329 return 0L;
330 }
Nandana Duttdb379fa2019-10-09 16:54:41 +0100331 MYLOGD("Module metadata package name: %s\n", package_name.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100332 int64_t version_code;
333 status = package_service->getVersionCodeForPackage(android::String16(package_name.c_str()),
334 &version_code);
335 if (!status.isOk()) {
336 MYLOGE("Failed to retrieve module metadata version: %s", status.toString8().c_str());
337 return 0L;
338 }
339 return version_code;
340}
341
mhasank2d75c442020-06-11 15:05:25 -0700342static bool PathExists(const std::string& path) {
343 struct stat sb;
344 return stat(path.c_str(), &sb) == 0;
345}
346
347static bool CopyFileToFile(const std::string& input_file, const std::string& output_file) {
348 if (input_file == output_file) {
349 MYLOGD("Skipping copying bugreport file since the destination is the same (%s)\n",
350 output_file.c_str());
351 return false;
352 }
353 else if (PathExists(output_file)) {
354 MYLOGD("Cannot overwrite an existing file (%s)\n", output_file.c_str());
355 return false;
356 }
357
358 MYLOGD("Going to copy bugreport file (%s) to %s\n", input_file.c_str(), output_file.c_str());
359 android::base::unique_fd out_fd(OpenForWrite(output_file));
360 return CopyFileToFd(input_file, out_fd.get());
361}
362
Primiano Tucci06d34202025-02-13 11:17:06 -0800363template <typename Func>
364size_t ForEachTrace(Func func) {
365 std::unique_ptr<DIR, decltype(&closedir)> traces_dir(opendir(SYSTEM_TRACE_DIR), closedir);
366
367 if (traces_dir == nullptr) {
368 MYLOGW("Unable to open directory %s: %s\n", SYSTEM_TRACE_DIR, strerror(errno));
369 return 0;
370 }
371
372 size_t traces_found = 0;
373 struct dirent* entry = nullptr;
374 while ((entry = readdir(traces_dir.get()))) {
375 if (entry->d_type != DT_REG) {
376 continue;
377 }
378 std::string trace_path = std::string(SYSTEM_TRACE_DIR) + "/" + entry->d_name;
379 if (access(trace_path.c_str(), F_OK) != 0) {
380 continue;
381 }
382 ++traces_found;
383 func(trace_path);
384 }
385 return traces_found;
386}
387
Nandana Dutt979388e2018-11-30 16:48:55 +0000388} // namespace
389} // namespace os
390} // namespace android
391
Felipe Leme678727a2016-09-21 17:22:11 -0700392static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
Felipe Lemebda15a02016-11-16 17:48:25 -0800393 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
Rhed Jaoe017f982020-07-21 17:58:41 +0800394 long dumpsysTimeoutMs = 0, int out_fd = STDOUT_FILENO) {
395 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs, out_fd);
396}
397static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
398 int out_fd) {
399 return ds.RunDumpsys(title, dumpsysArgs, Dumpstate::DEFAULT_DUMPSYS, 0, out_fd);
Felipe Leme678727a2016-09-21 17:22:11 -0700400}
401static int DumpFile(const std::string& title, const std::string& path) {
402 return ds.DumpFile(title, path);
403}
Felipe Lemee82a27d2016-01-05 13:35:44 -0800404
Felipe Lemee844a9d2016-09-21 15:01:39 -0700405// Relative directory (inside the zip) for all files copied as-is into the bugreport.
406static const std::string ZIP_ROOT_DIR = "FS";
407
Vishnu Naire97d6122018-01-18 13:58:56 -0800408static const std::string kProtoPath = "proto/";
409static const std::string kProtoExt = ".proto";
Jie Song9fbfad02017-06-20 16:29:42 -0700410static const std::string kDumpstateBoardFiles[] = {
411 "dumpstate_board.txt",
Felipe Leme95d6ca52017-08-01 16:35:56 -0700412 "dumpstate_board.bin"
Jie Song9fbfad02017-06-20 16:29:42 -0700413};
414static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
415
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700416static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Lemed071c682016-10-20 16:48:00 -0700417static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700418
Felipe Lemef0292972016-11-22 13:57:05 -0800419static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
420
Narayan Kamath8f788292017-05-25 13:20:39 +0100421/*
Narayan Kamathbd863722017-06-01 18:50:12 +0100422 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
Rhed Jao01dc0c62020-06-03 17:13:30 +0800423 * The returned vector is sorted by the mtimes of the dumps with descending
Chris Morinc2cba7a2022-02-01 17:06:50 -0800424 * order.
Narayan Kamath8f788292017-05-25 13:20:39 +0100425 */
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700426static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
Chris Morinc2cba7a2022-02-01 17:06:50 -0800427 const std::string& file_prefix) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100428 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100429
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700430 if (dump_dir == nullptr) {
431 MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno));
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700432 return std::vector<DumpData>();
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700433 }
434
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700435 std::vector<DumpData> dump_data;
Narayan Kamathbd863722017-06-01 18:50:12 +0100436 struct dirent* entry = nullptr;
437 while ((entry = readdir(dump_dir.get()))) {
438 if (entry->d_type != DT_REG) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100439 continue;
440 }
441
Narayan Kamathbd863722017-06-01 18:50:12 +0100442 const std::string base_name(entry->d_name);
443 if (base_name.find(file_prefix) != 0) {
444 continue;
445 }
446
447 const std::string abs_path = dir_path + base_name;
448 android::base::unique_fd fd(
449 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
450 if (fd == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700451 MYLOGW("Unable to open dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamathbd863722017-06-01 18:50:12 +0100452 break;
453 }
454
455 struct stat st = {};
456 if (fstat(fd, &st) == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700457 MYLOGW("Unable to stat dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamath8f788292017-05-25 13:20:39 +0100458 continue;
459 }
460
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700461 dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700462 }
Rhed Jao01dc0c62020-06-03 17:13:30 +0800463 if (!dump_data.empty()) {
464 std::sort(dump_data.begin(), dump_data.end(),
465 [](const auto& a, const auto& b) { return a.mtime > b.mtime; });
466 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100467
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700468 return dump_data;
Narayan Kamath8f788292017-05-25 13:20:39 +0100469}
470
Narayan Kamathbd863722017-06-01 18:50:12 +0100471static bool AddDumps(const std::vector<DumpData>::const_iterator start,
472 const std::vector<DumpData>::const_iterator end,
473 const char* type_name, const bool add_to_zip) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100474 bool dumped = false;
Narayan Kamathbd863722017-06-01 18:50:12 +0100475 for (auto it = start; it != end; ++it) {
476 const std::string& name = it->name;
477 const int fd = it->fd;
Narayan Kamath8f788292017-05-25 13:20:39 +0100478 dumped = true;
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100479
480 // Seek to the beginning of the file before dumping any data. A given
481 // DumpData entry might be dumped multiple times in the report.
482 //
483 // For example, the most recent ANR entry is dumped to the body of the
484 // main entry and it also shows up as a separate entry in the bugreport
485 // ZIP file.
486 if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) {
487 MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(),
488 strerror(errno));
489 }
490
Chris Morinc2cba7a2022-02-01 17:06:50 -0800491 if (add_to_zip) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800492 if (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd, /* timeout = */ 0ms) != OK) {
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100493 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100494 }
495 } else {
496 dump_file_from_fd(type_name, name.c_str(), fd);
497 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100498 }
499
500 return dumped;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700501}
502
Felipe Leme635ca312016-01-05 14:23:02 -0800503// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700504void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800505 char path[PATH_MAX];
506
507 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
508 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700509 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800510 char linkname[PATH_MAX];
511 ssize_t r = readlink(path, linkname, PATH_MAX);
512 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800513 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800514 return;
515 }
516 linkname[r] = '\0';
517
518 if (mount_points.find(linkname) == mount_points.end()) {
519 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700520 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700521 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
Felipe Leme635ca312016-01-05 14:23:02 -0800522 mount_points.insert(linkname);
523 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800524 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800525 }
526 }
527}
528
529void add_mountinfo() {
Felipe Leme678727a2016-09-21 17:22:11 -0700530 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800531 mount_points.clear();
Felipe Leme46b85da2016-11-21 17:40:45 -0800532 DurationReporter duration_reporter(title, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700533 for_each_pid(do_mountinfo, nullptr);
534 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800535}
536
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700537static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
538{
539 DIR *d;
540 struct dirent *de;
541 char path[PATH_MAX];
542
543 d = opendir(driverpath);
Yi Kong19d5c002018-07-20 13:39:55 -0700544 if (d == nullptr) {
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700545 return;
546 }
547
548 while ((de = readdir(d))) {
549 if (de->d_type != DT_LNK) {
550 continue;
551 }
552 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700553 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700554 }
555
556 closedir(d);
557}
558
Mark Salyzyn326842f2015-04-30 09:49:41 -0700559static bool skip_not_stat(const char *path) {
560 static const char stat[] = "/stat";
561 size_t len = strlen(path);
562 if (path[len - 1] == '/') { /* Directory? */
563 return false;
564 }
565 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
566}
567
Jeff Sharkey9df29d52023-02-06 14:26:30 -0700568static bool skip_wtf_strictmode(const char *path) {
569 if (strstr(path, "_wtf")) {
570 return true;
571 } else if (strstr(path, "_strictmode")) {
572 return true;
573 }
574 return false;
575}
576
Felipe Leme4c2d6632016-09-28 14:32:00 -0700577static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800578 return false;
579}
580
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700581unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700582
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800583//
584// stat offsets
585// Name units description
586// ---- ----- -----------
587// read I/Os requests number of read I/Os processed
588#define __STAT_READ_IOS 0
589// read merges requests number of read I/Os merged with in-queue I/O
590#define __STAT_READ_MERGES 1
591// read sectors sectors number of sectors read
592#define __STAT_READ_SECTORS 2
593// read ticks milliseconds total wait time for read requests
594#define __STAT_READ_TICKS 3
595// write I/Os requests number of write I/Os processed
596#define __STAT_WRITE_IOS 4
597// write merges requests number of write I/Os merged with in-queue I/O
598#define __STAT_WRITE_MERGES 5
599// write sectors sectors number of sectors written
600#define __STAT_WRITE_SECTORS 6
601// write ticks milliseconds total wait time for write requests
602#define __STAT_WRITE_TICKS 7
603// in_flight requests number of I/Os currently in flight
604#define __STAT_IN_FLIGHT 8
605// io_ticks milliseconds total time this block device has been active
606#define __STAT_IO_TICKS 9
607// time_in_queue milliseconds total wait time for all requests
608#define __STAT_IN_QUEUE 10
609#define __STAT_NUMBER_FIELD 11
610//
611// read I/Os, write I/Os
612// =====================
613//
614// These values increment when an I/O request completes.
615//
616// read merges, write merges
617// =========================
618//
619// These values increment when an I/O request is merged with an
620// already-queued I/O request.
621//
622// read sectors, write sectors
623// ===========================
624//
625// These values count the number of sectors read from or written to this
626// block device. The "sectors" in question are the standard UNIX 512-byte
627// sectors, not any device- or filesystem-specific block size. The
628// counters are incremented when the I/O completes.
629#define SECTOR_SIZE 512
630//
631// read ticks, write ticks
632// =======================
633//
634// These values count the number of milliseconds that I/O requests have
635// waited on this block device. If there are multiple I/O requests waiting,
636// these values will increase at a rate greater than 1000/second; for
637// example, if 60 read requests wait for an average of 30 ms, the read_ticks
638// field will increase by 60*30 = 1800.
639//
640// in_flight
641// =========
642//
643// This value counts the number of I/O requests that have been issued to
644// the device driver but have not yet completed. It does not include I/O
645// requests that are in the queue but not yet issued to the device driver.
646//
647// io_ticks
648// ========
649//
650// This value counts the number of milliseconds during which the device has
651// had I/O requests queued.
652//
653// time_in_queue
654// =============
655//
656// This value counts the number of milliseconds that I/O requests have waited
657// on this block device. If there are multiple I/O requests waiting, this
658// value will increase as the product of the number of milliseconds times the
659// number of requests waiting (see "read ticks" above for an example).
660#define S_TO_MS 1000
661//
662
Mark Salyzyn326842f2015-04-30 09:49:41 -0700663static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800664 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700665 bool z;
Yi Kong19d5c002018-07-20 13:39:55 -0700666 char *cp, *buffer = nullptr;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700667 size_t i = 0;
Josh Gao7c4258c2018-06-25 13:40:08 -0700668 FILE *fp = fdopen(dup(fd), "rb");
Mark Salyzyn326842f2015-04-30 09:49:41 -0700669 getline(&buffer, &i, fp);
670 fclose(fp);
671 if (!buffer) {
672 return -errno;
673 }
674 i = strlen(buffer);
675 while ((i > 0) && (buffer[i - 1] == '\n')) {
676 buffer[--i] = '\0';
677 }
678 if (!*buffer) {
679 free(buffer);
680 return 0;
681 }
682 z = true;
683 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800684 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700685 if (fields[i] != 0) {
686 z = false;
687 }
688 }
689 if (z) { /* never accessed */
690 free(buffer);
691 return 0;
692 }
693
Wei Wang509bb5d2017-06-09 14:42:12 -0700694 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
695 path += sizeof(BLK_DEV_SYS_DIR) - 1;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700696 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700697
698 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
699 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
700 "W-wait", "in-fli", "activ", "T-wait", path, buffer);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700701 free(buffer);
702
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800703 if (fields[__STAT_IO_TICKS]) {
704 unsigned long read_perf = 0;
705 unsigned long read_ios = 0;
706 if (fields[__STAT_READ_TICKS]) {
707 unsigned long long divisor = fields[__STAT_READ_TICKS]
708 * fields[__STAT_IO_TICKS];
709 read_perf = ((unsigned long long)SECTOR_SIZE
710 * fields[__STAT_READ_SECTORS]
711 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
712 / divisor;
713 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
714 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
715 / divisor;
716 }
717
718 unsigned long write_perf = 0;
719 unsigned long write_ios = 0;
720 if (fields[__STAT_WRITE_TICKS]) {
721 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
722 * fields[__STAT_IO_TICKS];
723 write_perf = ((unsigned long long)SECTOR_SIZE
724 * fields[__STAT_WRITE_SECTORS]
725 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
726 / divisor;
727 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
728 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
729 / divisor;
730 }
731
732 unsigned queue = (fields[__STAT_IN_QUEUE]
733 + (fields[__STAT_IO_TICKS] >> 1))
734 / fields[__STAT_IO_TICKS];
735
736 if (!write_perf && !write_ios) {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700737 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 -0800738 } else {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700739 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 -0800740 read_ios, write_perf, write_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800741 }
742
743 /* bugreport timeout factor adjustment */
744 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
745 worst_write_perf = write_perf;
746 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700747 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700748 return 0;
749}
750
Yao Chenbe3bbc12018-01-17 16:31:10 -0800751static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
752
Tom Cherryf4472f32020-08-05 09:31:17 -0700753// Returns the actual readable size of the given buffer or -1 on error.
754static long logcat_buffer_readable_size(const std::string& buffer) {
755 std::unique_ptr<logger_list, decltype(&android_logger_list_free)> logger_list{
756 android_logger_list_alloc(0, 0, 0), &android_logger_list_free};
757 auto logger = android_logger_open(logger_list.get(), android_name_to_log_id(buffer.c_str()));
758
759 return android_logger_get_log_readable_size(logger);
760}
761
762// Returns timeout in ms to read a list of buffers.
Yao Chenbe3bbc12018-01-17 16:31:10 -0800763static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
764 unsigned long timeout_ms = 0;
765 for (const auto& buffer : buffers) {
Tom Cherryf4472f32020-08-05 09:31:17 -0700766 long readable_size = logcat_buffer_readable_size(buffer);
767 if (readable_size > 0) {
768 // Engineering margin is ten-fold our guess.
769 timeout_ms += 10 * (readable_size + worst_write_perf) / worst_write_perf;
770 }
Yao Chenbe3bbc12018-01-17 16:31:10 -0800771 }
772 return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700773}
774
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800775// Opens a socket and returns its file descriptor.
776static int open_socket(const char* service);
777
Nandana Duttd2f5f082019-01-18 17:13:52 +0000778Dumpstate::ConsentCallback::ConsentCallback() : result_(UNAVAILABLE), start_time_(Nanotime()) {
779}
780
781android::binder::Status Dumpstate::ConsentCallback::onReportApproved() {
782 std::lock_guard<std::mutex> lock(lock_);
783 result_ = APPROVED;
784 MYLOGD("User approved consent to share bugreport\n");
Paul Chang0d2aad72020-02-13 20:04:03 +0800785
786 // Maybe copy screenshot so calling app can display the screenshot to the user as soon as
787 // consent is granted.
788 if (ds.options_->is_screenshot_copied) {
789 return android::binder::Status::ok();
790 }
791
792 if (!ds.options_->do_screenshot || ds.options_->screenshot_fd.get() == -1 ||
793 !ds.do_early_screenshot_) {
794 return android::binder::Status::ok();
795 }
796
797 bool copy_succeeded = android::os::CopyFileToFd(ds.screenshot_path_,
798 ds.options_->screenshot_fd.get());
Paul Chang0d2aad72020-02-13 20:04:03 +0800799 if (copy_succeeded) {
800 android::os::UnlinkAndLogOnError(ds.screenshot_path_);
Kunduz Baryktabasova3a5b65a2024-10-07 11:53:48 +0000801 } else {
802 MYLOGE("Failed to copy screenshot to a permanent file.\n");
803 copy_succeeded = android::os::CopyFileToFd(DEFAULT_SCREENSHOT_PATH,
804 ds.options_->screenshot_fd.get());
Paul Chang0d2aad72020-02-13 20:04:03 +0800805 }
Kunduz Baryktabasova3a5b65a2024-10-07 11:53:48 +0000806 ds.options_->is_screenshot_copied = copy_succeeded;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000807 return android::binder::Status::ok();
808}
809
810android::binder::Status Dumpstate::ConsentCallback::onReportDenied() {
811 std::lock_guard<std::mutex> lock(lock_);
812 result_ = DENIED;
813 MYLOGW("User denied consent to share bugreport\n");
814 return android::binder::Status::ok();
815}
816
817UserConsentResult Dumpstate::ConsentCallback::getResult() {
818 std::lock_guard<std::mutex> lock(lock_);
819 return result_;
820}
821
822uint64_t Dumpstate::ConsentCallback::getElapsedTimeMs() const {
Hunter Knepshieldf0a39052020-01-03 14:53:04 -0800823 return (Nanotime() - start_time_) / NANOS_PER_MILLI;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000824}
825
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700826void Dumpstate::PrintHeader() const {
MÃ¥rten Kongstad60195a72022-09-20 14:14:20 +0200827 std::string build, fingerprint, radio, bootloader, network, sdkversion;
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700828 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700829
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700830 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
831 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700832 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
833 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
834 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
MÃ¥rten Kongstad60195a72022-09-20 14:14:20 +0200835 sdkversion = android::base::GetProperty("ro.build.version.sdk", "(unknown)");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700836 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
Colin Crossf45fa6b2012-03-26 12:38:26 -0700837
Felipe Lemed8b94e52016-12-08 10:21:44 -0800838 printf("========================================================\n");
839 printf("== dumpstate: %s\n", date);
840 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700841
Felipe Lemed8b94e52016-12-08 10:21:44 -0800842 printf("\n");
843 printf("Build: %s\n", build.c_str());
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700844 // NOTE: fingerprint entry format is important for other tools.
Felipe Lemed8b94e52016-12-08 10:21:44 -0800845 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
846 printf("Bootloader: %s\n", bootloader.c_str());
847 printf("Radio: %s\n", radio.c_str());
848 printf("Network: %s\n", network.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100849 int64_t module_metadata_version = android::os::GetModuleMetadataVersion();
850 if (module_metadata_version != 0) {
851 printf("Module Metadata version: %" PRId64 "\n", module_metadata_version);
852 }
MÃ¥rten Kongstad60195a72022-09-20 14:14:20 +0200853 printf("Android SDK version: %s\n", sdkversion.c_str());
854 printf("SDK extensions: ");
855 RunCommandToFd(STDOUT_FILENO, "", {SDK_EXT_INFO, "--header"},
856 CommandOptions::WithTimeout(1).Always().DropRoot().Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700857
Felipe Lemed8b94e52016-12-08 10:21:44 -0800858 printf("Kernel: ");
Felipe Lemef0292972016-11-22 13:57:05 -0800859 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
Felipe Lemed8b94e52016-12-08 10:21:44 -0800860 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
Devin Moore09fde8d2023-03-21 16:28:22 +0000861 printf("Bootconfig: ");
862 DumpFileToFd(STDOUT_FILENO, "", "/proc/bootconfig");
Felipe Leme7709f8a2017-12-05 09:30:09 -0800863 printf("Uptime: ");
864 RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"},
865 CommandOptions::WithTimeout(1).Always().Build());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800866 printf("Bugreport format version: %s\n", version_.c_str());
Kevin Jeonfa64e642023-07-27 11:36:41 -0400867 printf(
868 "Dumpstate info: id=%d pid=%d dry_run=%d parallel_run=%d strict_run=%d args=%s "
869 "bugreport_mode=%s\n",
870 id_, pid_, PropertiesHelper::IsDryRun(), PropertiesHelper::IsParallelRun(),
871 PropertiesHelper::IsStrictRun(), options_->args.c_str(),
872 options_->bugreport_mode_string.c_str());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800873 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800874}
875
Felipe Leme24b66ee2016-06-16 10:55:26 -0700876// List of file extensions that can cause a zip file attachment to be rejected by some email
877// service providers.
878static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
879 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
880 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
881 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
882};
883
Vishnu Naire97d6122018-01-18 13:58:56 -0800884status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd,
885 std::chrono::milliseconds timeout = 0ms) {
Felipe Leme24b66ee2016-06-16 10:55:26 -0700886 std::string valid_name = entry_name;
887
888 // Rename extension if necessary.
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -0700889 size_t idx = entry_name.rfind('.');
Felipe Leme24b66ee2016-06-16 10:55:26 -0700890 if (idx != std::string::npos) {
891 std::string extension = entry_name.substr(idx);
892 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
893 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
894 valid_name = entry_name + ".renamed";
895 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
896 }
897 }
898
Felipe Leme6fe9db62016-02-12 09:04:16 -0800899 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
900 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Kevin Jeon9bbe0ac2022-05-05 22:05:43 +0000901 size_t flags = ZipWriter::kCompress | ZipWriter::kDefaultCompression;
902 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), flags,
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700903 get_mtime(fd, ds.now_));
Felipe Leme1d486fe2016-10-14 18:06:47 -0700904 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700905 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700906 ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800907 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800908 }
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000909 bool finished_entry = false;
910 auto finish_entry = [this, &finished_entry] {
911 if (!finished_entry) {
912 // This should only be called when we're going to return an earlier error,
913 // which would've been logged. This may imply the file is already corrupt
914 // and any further logging from FinishEntry is more likely to mislead than
915 // not.
916 this->zip_writer_->FinishEntry();
917 }
918 };
919 auto scope_guard = android::base::make_scope_guard(finish_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -0800920 auto start = std::chrono::steady_clock::now();
921 auto end = start + timeout;
922 struct pollfd pfd = {fd, POLLIN};
Felipe Lemee82a27d2016-01-05 13:35:44 -0800923
Felipe Leme770410d2016-01-26 17:07:14 -0800924 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800925 while (1) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800926 if (timeout.count() > 0) {
927 // lambda to recalculate the timeout.
928 auto time_left_ms = [end]() {
929 auto now = std::chrono::steady_clock::now();
930 auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
931 return std::max(diff.count(), 0LL);
932 };
933
934 int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
935 if (rc < 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000936 MYLOGE("Error in poll while adding from fd to zip entry %s:%s\n",
937 entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800938 return -errno;
939 } else if (rc == 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000940 MYLOGE("Timed out adding from fd to zip entry %s:%s Timeout:%lldms\n",
Vishnu Naire97d6122018-01-18 13:58:56 -0800941 entry_name.c_str(), strerror(errno), timeout.count());
942 return TIMED_OUT;
943 }
944 }
945
Zach Riggle22200402016-08-18 01:01:24 -0400946 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800947 if (bytes_read == 0) {
948 break;
949 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800950 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800951 return -errno;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800952 }
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700953 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800954 if (err) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700955 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800956 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800957 }
958 }
959
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700960 err = zip_writer_->FinishEntry();
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000961 finished_entry = true;
Felipe Leme1d486fe2016-10-14 18:06:47 -0700962 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700963 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800964 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800965 }
966
Vishnu Naire97d6122018-01-18 13:58:56 -0800967 return OK;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800968}
969
Felipe Leme1d486fe2016-10-14 18:06:47 -0700970bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
971 android::base::unique_fd fd(
972 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700973 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800974 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800975 return false;
976 }
977
Vishnu Naire97d6122018-01-18 13:58:56 -0800978 return (AddZipEntryFromFd(entry_name, fd.get()) == OK);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800979}
980
981/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700982static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800983 return (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) == OK) ? 0 : 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800984}
985
Felipe Leme1d486fe2016-10-14 18:06:47 -0700986void Dumpstate::AddDir(const std::string& dir, bool recursive) {
Felipe Leme678727a2016-09-21 17:22:11 -0700987 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
Felipe Leme46b85da2016-11-21 17:40:45 -0800988 DurationReporter duration_reporter(dir, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700989 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800990}
991
Felipe Leme1d486fe2016-10-14 18:06:47 -0700992bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800993 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Kevin Jeon9bbe0ac2022-05-05 22:05:43 +0000994 size_t flags = ZipWriter::kCompress | ZipWriter::kDefaultCompression;
995 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), flags, ds.now_);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700996 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700997 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700998 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800999 return false;
1000 }
1001
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001002 err = zip_writer_->WriteBytes(content.c_str(), content.length());
Felipe Leme1d486fe2016-10-14 18:06:47 -07001003 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001004 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07001005 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -08001006 return false;
1007 }
1008
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001009 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -07001010 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001011 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -08001012 return false;
1013 }
1014
1015 return true;
1016}
1017
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001018static void DoKmsg() {
1019 struct stat st;
1020 if (!stat(PSTORE_LAST_KMSG, &st)) {
1021 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
1022 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
1023 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
1024 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
1025 } else {
1026 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
1027 DumpFile("LAST KMSG", "/proc/last_kmsg");
1028 }
1029}
1030
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001031static void DoKernelLogcat() {
Yao Chenbe3bbc12018-01-17 16:31:10 -08001032 unsigned long timeout_ms = logcat_timeout({"kernel"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001033 RunCommand(
1034 "KERNEL LOG",
1035 {"logcat", "-b", "kernel", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1036 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1037}
1038
Nandana Duttdb379fa2019-10-09 16:54:41 +01001039static void DoSystemLogcat(time_t since) {
1040 char since_str[80];
1041 strftime(since_str, sizeof(since_str), "%Y-%m-%d %H:%M:%S.000", localtime(&since));
1042
1043 unsigned long timeout_ms = logcat_timeout({"main", "system", "crash"});
1044 RunCommand("SYSTEM LOG",
1045 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v", "-T",
1046 since_str},
1047 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1048}
1049
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001050static void DoRadioLogcat() {
1051 unsigned long timeout_ms = logcat_timeout({"radio"});
1052 RunCommand(
1053 "RADIO LOG",
1054 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1055 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
1056}
1057
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001058static void DoLogcat() {
Vishnu Nair6921f802017-11-22 09:17:23 -08001059 unsigned long timeout_ms;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001060 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
1061 // calculate timeout
Yao Chenbe3bbc12018-01-17 16:31:10 -08001062 timeout_ms = logcat_timeout({"main", "system", "crash"});
Tony Makae737652017-03-30 17:47:09 +01001063 RunCommand("SYSTEM LOG",
Vishnu Nair6921f802017-11-22 09:17:23 -08001064 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1065 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -08001066 timeout_ms = logcat_timeout({"events"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001067 RunCommand(
1068 "EVENT LOG",
1069 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001070 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Yao Chenbe3bbc12018-01-17 16:31:10 -08001071 timeout_ms = logcat_timeout({"stats"});
1072 RunCommand(
1073 "STATS LOG",
1074 {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001075 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001076 DoRadioLogcat();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001077
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001078 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001079 RunCommand("LAST LOGCAT", {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable",
1080 "-v", "uid", "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001081}
1082
Mike Ma5c267872019-08-21 11:31:34 -07001083static void DumpIncidentReport() {
Mike Ma5c267872019-08-21 11:31:34 -07001084 const std::string path = ds.bugreport_internal_dir_ + "/tmp_incident_report";
1085 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1086 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1087 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1088 if (fd < 0) {
1089 MYLOGE("Could not open %s to dump incident report.\n", path.c_str());
1090 return;
1091 }
Kevin Jeonfa64e642023-07-27 11:36:41 -04001092 RunCommandToFd(fd, "", {"incident", "-u"},
1093 CommandOptions::WithTimeout(PropertiesHelper::IsStrictRun() ? 20 : 120).Build());
Mike Ma5c267872019-08-21 11:31:34 -07001094 bool empty = 0 == lseek(fd, 0, SEEK_END);
1095 if (!empty) {
1096 // Use a different name from "incident.proto"
1097 // /proto/incident.proto is reserved for incident service dump
1098 // i.e. metadata for debugging.
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001099 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "incident_report" + kProtoExt,
1100 path);
1101 } else {
1102 unlink(path.c_str());
Mike Ma5c267872019-08-21 11:31:34 -07001103 }
Mike Ma5c267872019-08-21 11:31:34 -07001104}
1105
Aaron Huang24d215d2022-04-27 18:51:16 +08001106static void DumpNetstatsProto() {
1107 const std::string path = ds.bugreport_internal_dir_ + "/tmp_netstats_proto";
1108 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1109 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1110 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1111 if (fd < 0) {
1112 MYLOGE("Could not open %s to dump netstats proto.\n", path.c_str());
1113 return;
1114 }
1115 RunCommandToFd(fd, "", {"dumpsys", "netstats", "--proto"},
Kevin Jeon2fb3dd62022-09-28 18:48:55 +00001116 CommandOptions::WithTimeout(5).Build());
Aaron Huang24d215d2022-04-27 18:51:16 +08001117 bool empty = 0 == lseek(fd, 0, SEEK_END);
1118 if (!empty) {
1119 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "netstats" + kProtoExt,
1120 path);
1121 } else {
1122 unlink(path.c_str());
1123 }
1124}
1125
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001126static void MaybeAddSystemTraceToZip() {
1127 // This function copies into the .zip the system trace that was snapshotted
Kean Mariottica20f2d2023-12-15 09:34:25 +00001128 // by the early call to MaybeSnapshotSystemTraceAsync(), if any background
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001129 // tracing was happening.
Primiano Tucci06d34202025-02-13 11:17:06 -08001130 size_t traces_found = android::os::ForEachTrace([&](const std::string& trace_path) {
1131 ds.AddZipEntry(ZIP_ROOT_DIR + trace_path, trace_path);
1132 android::os::UnlinkAndLogOnError(trace_path);
1133 });
1134
1135 if (traces_found == 0 && !PropertiesHelper::IsUserBuild()) {
1136 MYLOGI(
1137 "No system traces found. Check for previously uploaded traces by looking for "
1138 "go/trace-uuid in logcat")
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001139 }
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001140}
1141
Sunny Goyal35949782019-11-19 15:54:36 -08001142static void DumpVisibleWindowViews() {
Sunny Goyal35949782019-11-19 15:54:36 -08001143 DurationReporter duration_reporter("VISIBLE WINDOW VIEWS");
1144 const std::string path = ds.bugreport_internal_dir_ + "/tmp_visible_window_views";
1145 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1146 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1147 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1148 if (fd < 0) {
1149 MYLOGE("Could not open %s to dump visible views.\n", path.c_str());
1150 return;
1151 }
1152 RunCommandToFd(fd, "", {"cmd", "window", "dump-visible-window-views"},
Kevin Jeon774abde2022-09-28 18:20:43 +00001153 CommandOptions::WithTimeout(10).Build());
Sunny Goyal35949782019-11-19 15:54:36 -08001154 bool empty = 0 == lseek(fd, 0, SEEK_END);
1155 if (!empty) {
1156 ds.AddZipEntry("visible_windows.zip", path);
1157 } else {
1158 MYLOGW("Failed to dump visible windows\n");
1159 }
1160 unlink(path.c_str());
1161}
1162
Jayachandran Ca94c7172017-06-10 15:08:12 -07001163static void DumpIpTablesAsRoot() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001164 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
1165 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +09001166 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001167 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +09001168 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
1169 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
1170 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
1171 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001172}
1173
Woody Lin20767a92022-11-29 15:50:24 +08001174static void DumpShutdownCheckpoints() {
1175 const bool shutdown_checkpoints_dumped = AddDumps(
1176 ds.shutdown_checkpoints_.begin(), ds.shutdown_checkpoints_.end(),
1177 "SHUTDOWN CHECKPOINTS", false /* add_to_zip */);
1178 if (!shutdown_checkpoints_dumped) {
1179 printf("*** NO SHUTDOWN CHECKPOINTS to dump in %s\n\n",
1180 SHUTDOWN_CHECKPOINTS_DIR.c_str());
1181 }
1182}
1183
David Andersond9ba4752018-12-11 18:26:59 -08001184static void DumpDynamicPartitionInfo() {
1185 if (!::android::base::GetBoolProperty("ro.boot.dynamic_partitions", false)) {
1186 return;
1187 }
1188
1189 RunCommand("LPDUMP", {"lpdump", "--all"});
David Anderson6650ade2019-10-02 15:18:59 -07001190 RunCommand("DEVICE-MAPPER", {"gsid", "dump-device-mapper"});
David Andersond9ba4752018-12-11 18:26:59 -08001191}
1192
Chris Morin5a50d482022-02-01 17:41:18 -08001193static void AddAnrTraceDir(const std::string& anr_traces_dir) {
Narayan Kamath8f788292017-05-25 13:20:39 +01001194 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
1195 anr_traces_dir.c_str());
1196
1197 // If we're here, dump_traces_path will always be a temporary file
1198 // (created with mkostemp or similar) that contains dumps taken earlier
1199 // on in the process.
1200 if (dump_traces_path != nullptr) {
Chris Morin5a50d482022-02-01 17:41:18 -08001201 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
1202 dump_traces_path);
1203 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
Narayan Kamath8f788292017-05-25 13:20:39 +01001204
1205 const int ret = unlink(dump_traces_path);
1206 if (ret == -1) {
1207 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
1208 strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -07001209 }
1210 }
1211
Narayan Kamathbd863722017-06-01 18:50:12 +01001212 // Add a specific message for the first ANR Dump.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001213 if (ds.anr_data_.size() > 0) {
Chris Morin5a50d482022-02-01 17:41:18 -08001214 // The "last" ANR will always be present in the body of the main entry.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001215 AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1,
Chris Morin5a50d482022-02-01 17:41:18 -08001216 "VM TRACES AT LAST ANR", false /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001217
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001218 // Historical ANRs are always included as separate entries in the bugreport zip file.
Chris Morin5a50d482022-02-01 17:41:18 -08001219 AddDumps(ds.anr_data_.begin(), ds.anr_data_.end(),
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001220 "HISTORICAL ANR", true /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001221 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +01001222 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
1223 }
Andy Hungd62f7e62024-01-11 15:47:52 -08001224
1225 // Add Java anr traces (such as generated by the Finalizer Watchdog).
1226 AddDumps(ds.anr_trace_data_.begin(), ds.anr_trace_data_.end(), "JAVA ANR TRACES",
1227 true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001228}
1229
1230static void AddAnrTraceFiles() {
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001231 std::string anr_traces_dir = "/data/anr";
Narayan Kamath8f788292017-05-25 13:20:39 +01001232
Chris Morin5a50d482022-02-01 17:41:18 -08001233 AddAnrTraceDir(anr_traces_dir);
Narayan Kamath8f788292017-05-25 13:20:39 +01001234
Makoto Onuki83ec63f2019-01-31 17:08:59 -08001235 RunCommand("ANR FILES", {"ls", "-lt", ANR_DIR});
1236
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001237 // Slow traces for slow operations.
Felipe Lemee184f662016-10-27 10:04:47 -07001238 struct stat st;
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001239 int i = 0;
1240 while (true) {
1241 const std::string slow_trace_path =
1242 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
1243 if (stat(slow_trace_path.c_str(), &st)) {
1244 // No traces file at this index, done with the files.
1245 break;
Felipe Lemee184f662016-10-27 10:04:47 -07001246 }
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001247 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
1248 i++;
Felipe Lemee184f662016-10-27 10:04:47 -07001249 }
1250}
1251
Wei Wang509bb5d2017-06-09 14:42:12 -07001252static void DumpBlockStatFiles() {
1253 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -07001254
Wei Wang1dc1ef52017-06-12 11:28:37 -07001255 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
1256
1257 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001258 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1259 return;
1260 }
1261
1262 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -07001263 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001264 if ((d->d_name[0] == '.')
1265 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1266 || (d->d_name[1] == '\0'))) {
1267 continue;
1268 }
1269 const std::string new_path =
1270 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1271 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1272 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1273 printf("\n");
1274 }
Wei Wang1dc1ef52017-06-12 11:28:37 -07001275 return;
Wei Wang509bb5d2017-06-09 14:42:12 -07001276}
Jayachandran Ca94c7172017-06-10 15:08:12 -07001277
1278static void DumpPacketStats() {
1279 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
Jayachandran Ca94c7172017-06-10 15:08:12 -07001280}
1281
1282static void DumpIpAddrAndRules() {
1283 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
Ray Chencbf278a2023-11-20 07:49:45 +00001284 RunCommand("NETWORK INTERFACES", {"ip", "-s", "link"});
Jayachandran Ca94c7172017-06-10 15:08:12 -07001285 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1286 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1287 RunCommand("IP RULES", {"ip", "rule", "show"});
1288 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1289}
1290
Alessio Balsini9e332a72024-12-10 15:31:57 +00001291static void DumpKernelMemoryAllocations() {
1292 if (!access("/proc/allocinfo", F_OK)) {
1293 // Print the top 100 biggest memory allocations of at least one byte.
1294 // The output is sorted by size, descending.
1295 RunCommand("KERNEL MEMORY ALLOCATIONS",
1296 {"alloctop", "--once", "--sort", "s", "--min", "1", "--lines", "100"});
1297 }
1298}
1299
Steven Moreland0d564d52025-01-10 22:24:57 +00001300// BAD - See README.md: "Dumpstate philosophy: exec not link"
1301// This should all be moved into a separate binary rather than have complex logic here.
Nandana Dutt5c390032019-03-12 10:52:56 +00001302static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, int priority,
1303 std::chrono::milliseconds timeout,
1304 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001305 auto start = std::chrono::steady_clock::now();
Vishnu Naire97d6122018-01-18 13:58:56 -08001306 sp<android::IServiceManager> sm = defaultServiceManager();
1307 Dumpsys dumpsys(sm.get());
Vishnu Naire97d6122018-01-18 13:58:56 -08001308 Vector<String16> args;
1309 Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
Vishnu Naire97d6122018-01-18 13:58:56 -08001310 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1311 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001312 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001313 std::string path(title);
1314 path.append(" - ").append(String8(service).c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -08001315 size_t bytes_written = 0;
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001316 if (PropertiesHelper::IsDryRun()) {
1317 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1318 dumpsys.writeDumpFooter(STDOUT_FILENO, service, std::chrono::milliseconds(1));
1319 } else {
Devin Mooref492c1a2023-03-15 19:19:03 +00001320 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP | Dumpsys::TYPE_PID |
1321 Dumpsys::TYPE_CLIENTS | Dumpsys::TYPE_THREAD,
Devin Mooreae68df22023-02-24 20:59:51 +00001322 service, args);
1323 if (status == OK) {
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001324 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1325 std::chrono::duration<double> elapsed_seconds;
1326 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH &&
1327 service == String16("meminfo")) {
1328 // Use a longer timeout for meminfo, since 30s is not always enough.
1329 status = dumpsys.writeDump(STDOUT_FILENO, service, 60s,
1330 /* as_proto = */ false, elapsed_seconds,
1331 bytes_written);
1332 } else {
1333 status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
1334 /* as_proto = */ false, elapsed_seconds,
1335 bytes_written);
1336 }
1337 dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
1338 bool dump_complete = (status == OK);
1339 dumpsys.stopDumpThread(dump_complete);
Devin Moorecdfa4602023-03-16 20:49:39 +00001340 } else {
1341 MYLOGE("Failed to start dump thread for service: %s, status: %d",
1342 String8(service).c_str(), status);
Gavin Corkeryfac7e2b2021-07-08 22:39:02 +01001343 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001344 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001345
1346 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1347 std::chrono::steady_clock::now() - start);
1348 if (elapsed_duration > timeout) {
1349 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1350 elapsed_duration.count());
1351 break;
1352 }
1353 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001354 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001355}
1356
Vishnu Nair64afc022018-02-01 15:29:34 -08001357static void RunDumpsysText(const std::string& title, int priority,
1358 std::chrono::milliseconds timeout,
1359 std::chrono::milliseconds service_timeout) {
1360 DurationReporter duration_reporter(title);
1361 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1362 fsync(STDOUT_FILENO);
1363 RunDumpsysTextByPriority(title, priority, timeout, service_timeout);
1364}
1365
1366/* Dump all services registered with Normal or Default priority. */
Nandana Dutt5c390032019-03-12 10:52:56 +00001367static Dumpstate::RunStatus RunDumpsysTextNormalPriority(const std::string& title,
1368 std::chrono::milliseconds timeout,
1369 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001370 DurationReporter duration_reporter(title);
1371 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1372 fsync(STDOUT_FILENO);
1373 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout,
1374 service_timeout);
Nandana Dutt5c390032019-03-12 10:52:56 +00001375
1376 RETURN_IF_USER_DENIED_CONSENT();
1377
1378 return RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1379 service_timeout);
Vishnu Nair64afc022018-02-01 15:29:34 -08001380}
1381
Steven Moreland0d564d52025-01-10 22:24:57 +00001382// BAD - See README.md: "Dumpstate philosophy: exec not link"
1383// This should all be moved into a separate binary rather than have complex logic here.
Nandana Dutt5c390032019-03-12 10:52:56 +00001384static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priority,
1385 std::chrono::milliseconds timeout,
1386 std::chrono::milliseconds service_timeout) {
Vishnu Naire97d6122018-01-18 13:58:56 -08001387 sp<android::IServiceManager> sm = defaultServiceManager();
1388 Dumpsys dumpsys(sm.get());
1389 Vector<String16> args;
1390 Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
1391 DurationReporter duration_reporter(title);
1392
1393 auto start = std::chrono::steady_clock::now();
1394 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
1395 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001396 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001397 std::string path(kProtoPath);
1398 path.append(String8(service).c_str());
1399 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
1400 path.append("_CRITICAL");
1401 } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
1402 path.append("_HIGH");
1403 }
1404 path.append(kProtoExt);
Steven Morelandcbd69fc2021-07-20 20:45:43 +00001405 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP, service, args);
Vishnu Naire97d6122018-01-18 13:58:56 -08001406 if (status == OK) {
1407 status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
1408 bool dumpTerminated = (status == OK);
1409 dumpsys.stopDumpThread(dumpTerminated);
1410 }
1411 ZipWriter::FileEntry file_entry;
1412 ds.zip_writer_->GetLastEntry(&file_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -08001413
1414 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1415 std::chrono::steady_clock::now() - start);
1416 if (elapsed_duration > timeout) {
1417 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1418 elapsed_duration.count());
1419 break;
1420 }
1421 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001422 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001423}
1424
Nandana Dutta7db6342018-11-21 14:53:34 +00001425// Runs dumpsys on services that must dump first and will take less than 100ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001426static Dumpstate::RunStatus RunDumpsysCritical() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001427 RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1428 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Nandana Dutt5c390032019-03-12 10:52:56 +00001429
1430 RETURN_IF_USER_DENIED_CONSENT();
1431
1432 return RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1433 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Vishnu Nair780b1282017-10-10 13:57:24 -07001434}
1435
1436// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001437static Dumpstate::RunStatus RunDumpsysHigh() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001438 // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
1439 // high priority. Reduce timeout once they are able to dump in a shorter time or
1440 // moved to a parallel task.
1441 RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1442 /* timeout= */ 90s, /* service_timeout= */ 30s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001443
1444 RETURN_IF_USER_DENIED_CONSENT();
1445
1446 return RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1447 /* timeout= */ 5s, /* service_timeout= */ 1s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001448}
1449
1450// Runs dumpsys on services that must dump but can take up to 10s to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001451static Dumpstate::RunStatus RunDumpsysNormal() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001452 RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001453
1454 RETURN_IF_USER_DENIED_CONSENT();
1455
1456 return RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1457 /* timeout= */ 90s, /* service_timeout= */ 10s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001458}
1459
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001460/*
1461 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1462 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1463 * if it's not running in the parallel task.
1464 */
Steven Moreland0d564d52025-01-10 22:24:57 +00001465// BAD - See README.md: "Dumpstate philosophy: exec not link"
1466// This should all be moved into a separate binary rather than have complex logic here.
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001467static void DumpHals(int out_fd = STDOUT_FILENO) {
Yifan Hong30528a22020-08-07 18:24:06 -07001468 RunCommand("HARDWARE HALS", {"lshal", "--all", "--types=all"},
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001469 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build(),
1470 false, out_fd);
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001471
Steven Moreland44cd9482018-01-04 16:24:13 -08001472 using android::hidl::manager::V1_0::IServiceManager;
1473 using android::hardware::defaultServiceManager;
1474
1475 sp<IServiceManager> sm = defaultServiceManager();
1476 if (sm == nullptr) {
1477 MYLOGE("Could not retrieve hwservicemanager to dump hals.\n");
1478 return;
1479 }
1480
1481 auto ret = sm->list([&](const auto& interfaces) {
1482 for (const std::string& interface : interfaces) {
1483 std::string cleanName = interface;
Steven Morelandc6b1fc22023-07-26 23:53:58 +00001484 std::replace_if(
1485 cleanName.begin(), cleanName.end(),
1486 [](char c) {
1487 return !isalnum(c) && std::string("@-_.").find(c) == std::string::npos;
1488 },
1489 '_');
Nandana Dutt979388e2018-11-30 16:48:55 +00001490 const std::string path = ds.bugreport_internal_dir_ + "/lshal_debug_" + cleanName;
Steven Moreland44cd9482018-01-04 16:24:13 -08001491
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001492 bool empty = false;
Steven Moreland44cd9482018-01-04 16:24:13 -08001493 {
1494 auto fd = android::base::unique_fd(
1495 TEMP_FAILURE_RETRY(open(path.c_str(),
1496 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1497 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1498 if (fd < 0) {
1499 MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str());
1500 continue;
1501 }
1502 RunCommandToFd(fd,
1503 "",
Steven Morelandc81cd3c2018-01-18 14:36:26 -08001504 {"lshal", "debug", "-E", interface},
Steven Moreland44cd9482018-01-04 16:24:13 -08001505 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1506
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001507 empty = 0 == lseek(fd, 0, SEEK_END);
Steven Moreland44cd9482018-01-04 16:24:13 -08001508 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001509 if (!empty) {
1510 ds.EnqueueAddZipEntryAndCleanupIfNeeded("lshal-debug/" + cleanName + ".txt",
1511 path);
1512 } else {
1513 unlink(path.c_str());
1514 }
Steven Moreland44cd9482018-01-04 16:24:13 -08001515 }
1516 });
1517
1518 if (!ret.isOk()) {
1519 MYLOGE("Could not list hals from hwservicemanager.\n");
1520 }
1521}
1522
Steven Moreland0d564d52025-01-10 22:24:57 +00001523// BAD - See README.md: "Dumpstate philosophy: exec not link"
1524// This should all be moved into a separate binary rather than have complex logic here.
1525//
Devin Moore8df81bb2022-06-08 22:47:02 +00001526// Dump all of the files that make up the vendor interface.
1527// See the files listed in dumpFileList() for the latest list of files.
1528static void DumpVintf() {
Devin Moore16271d92022-09-22 18:28:48 +00001529
1530 const std::string sku = android::base::GetProperty("ro.boot.product.hardware.sku", "");
1531 const auto vintfFiles = android::vintf::details::dumpFileList(sku);
Devin Moore8df81bb2022-06-08 22:47:02 +00001532 for (const auto vintfFile : vintfFiles) {
1533 struct stat st;
1534 if (stat(vintfFile.c_str(), &st) == 0) {
1535 if (S_ISDIR(st.st_mode)) {
1536 ds.AddDir(vintfFile, true /* recursive */);
1537 } else {
1538 ds.EnqueueAddZipEntryAndCleanupIfNeeded(ZIP_ROOT_DIR + vintfFile,
1539 vintfFile);
1540 }
1541 }
1542 }
1543}
1544
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001545static void DumpExternalFragmentationInfo() {
1546 struct stat st;
1547 if (stat("/proc/buddyinfo", &st) != 0) {
1548 MYLOGE("Unable to dump external fragmentation info\n");
1549 return;
1550 }
1551
1552 printf("------ EXTERNAL FRAGMENTATION INFO ------\n");
1553 std::ifstream ifs("/proc/buddyinfo");
1554 auto unusable_index_regex = std::regex{"Node\\s+([0-9]+),\\s+zone\\s+(\\S+)\\s+(.*)"};
Steven Moreland0d564d52025-01-10 22:24:57 +00001555 // BAD - See README.md: "Dumpstate philosophy: exec not link"
1556 // This should all be moved into a separate binary rather than have complex logic here.
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001557 for (std::string line; std::getline(ifs, line);) {
1558 std::smatch match_results;
1559 if (std::regex_match(line, match_results, unusable_index_regex)) {
1560 std::stringstream free_pages(std::string{match_results[3]});
1561 std::vector<int> free_pages_per_order(std::istream_iterator<int>{free_pages},
1562 std::istream_iterator<int>());
1563
1564 int total_free_pages = 0;
1565 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1566 total_free_pages += (free_pages_per_order[i] * std::pow(2, i));
1567 }
1568
1569 printf("Node %s, zone %8s", match_results[1].str().c_str(),
1570 match_results[2].str().c_str());
1571
1572 int usable_free_pages = total_free_pages;
1573 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1574 auto unusable_index = (total_free_pages - usable_free_pages) /
1575 static_cast<double>(total_free_pages);
1576 printf(" %5.3f", unusable_index);
1577 usable_free_pages -= (free_pages_per_order[i] * std::pow(2, i));
1578 }
1579
1580 printf("\n");
1581 }
1582 }
1583 printf("\n");
1584}
1585
mhasankd451a472020-05-26 18:02:39 -07001586static void DumpstateLimitedOnly() {
EdenSue8fe4522023-11-20 15:37:23 +08001587 // Trimmed-down version of dumpstate to only include a allowlisted
mhasankd451a472020-05-26 18:02:39 -07001588 // set of logs (system log, event log, and system server / system app
1589 // crashes, and networking logs). See b/136273873 and b/138459828
1590 // for context.
1591 DurationReporter duration_reporter("DUMPSTATE");
1592 unsigned long timeout_ms;
1593 // calculate timeout
1594 timeout_ms = logcat_timeout({"main", "system", "crash"});
1595 RunCommand("SYSTEM LOG",
1596 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1597 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1598 timeout_ms = logcat_timeout({"events"});
1599 RunCommand(
1600 "EVENT LOG",
1601 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1602 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1603
1604 printf("========================================================\n");
1605 printf("== Networking Service\n");
1606 printf("========================================================\n");
1607
1608 RunDumpsys("DUMPSYS NETWORK_SERVICE_LIMITED", {"wifi", "-a"},
1609 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hugo Benichiaa162682020-10-30 23:28:56 +09001610 RunDumpsys("DUMPSYS CONNECTIVITY REQUESTS", {"connectivity", "requests"},
1611 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
mhasankd451a472020-05-26 18:02:39 -07001612
1613 printf("========================================================\n");
Chuwei Hecc54a252024-07-25 15:18:36 +09001614 printf("== Networking Policy\n");
1615 printf("========================================================\n");
1616
1617 RunDumpsys("DUMPSYS NETWORK POLICY", {"netpolicy"}, CommandOptions::WithTimeout(90).Build(),
1618 SEC_TO_MSEC(10));
1619
1620 printf("========================================================\n");
mhasankd451a472020-05-26 18:02:39 -07001621 printf("== Dropbox crashes\n");
1622 printf("========================================================\n");
1623
1624 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1625 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1626
Bryan Yuefb85d92024-02-02 13:37:06 +00001627
1628 printf("========================================================\n");
1629 printf("== ANR Traces\n");
1630 printf("========================================================\n");
1631
Bryan Yucf038cf2024-05-08 09:25:25 +00001632 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX);
Bryan Yuefb85d92024-02-02 13:37:06 +00001633 AddAnrTraceFiles();
1634
mhasankd451a472020-05-26 18:02:39 -07001635 printf("========================================================\n");
1636 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1637 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1638 printf("========================================================\n");
1639 printf("== dumpstate: done (id %d)\n", ds.id_);
1640 printf("========================================================\n");
1641}
1642
Rhed Jaoe017f982020-07-21 17:58:41 +08001643/*
1644 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1645 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1646 * if it's not running in the parallel task.
1647 */
1648static void DumpCheckins(int out_fd = STDOUT_FILENO) {
1649 dprintf(out_fd, "========================================================\n");
1650 dprintf(out_fd, "== Checkins\n");
1651 dprintf(out_fd, "========================================================\n");
1652
1653 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"}, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001654 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"}, out_fd);
1655 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"}, out_fd);
1656 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"}, out_fd);
1657 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"}, out_fd);
1658}
1659
1660/*
1661 * Runs dumpsys on activity service to dump all application activities, services
1662 * and providers in the device.
1663 *
1664 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1665 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1666 * if it's not running in the parallel task.
1667 */
1668static void DumpAppInfos(int out_fd = STDOUT_FILENO) {
1669 dprintf(out_fd, "========================================================\n");
1670 dprintf(out_fd, "== Running Application Activities\n");
1671 dprintf(out_fd, "========================================================\n");
1672
1673 // The following dumpsys internally collects output from running apps, so it can take a long
1674 // time. So let's extend the timeout.
1675
1676 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1677
1678 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1679
1680 dprintf(out_fd, "========================================================\n");
1681 dprintf(out_fd, "== Running Application Services (platform)\n");
1682 dprintf(out_fd, "========================================================\n");
1683
1684 RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
1685 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1686
1687 dprintf(out_fd, "========================================================\n");
1688 dprintf(out_fd, "== Running Application Services (non-platform)\n");
1689 dprintf(out_fd, "========================================================\n");
1690
1691 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1692 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1693
1694 dprintf(out_fd, "========================================================\n");
1695 dprintf(out_fd, "== Running Application Providers (platform)\n");
1696 dprintf(out_fd, "========================================================\n");
1697
1698 RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
Rhed Jaob049f182021-01-11 21:08:43 +08001699 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001700
1701 dprintf(out_fd, "========================================================\n");
1702 dprintf(out_fd, "== Running Application Providers (non-platform)\n");
1703 dprintf(out_fd, "========================================================\n");
1704
1705 RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1706 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1707}
1708
Nandana Dutt5c390032019-03-12 10:52:56 +00001709// Dumps various things. Returns early with status USER_CONSENT_DENIED if user denies consent
1710// via the consent they are shown. Ignores other errors that occur while running various
1711// commands. The consent checking is currently done around long running tasks, which happen to
1712// be distributed fairly evenly throughout the function.
Kean Mariotti306633e2022-09-05 16:30:47 +00001713Dumpstate::RunStatus Dumpstate::dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001714 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001715
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001716 // Enqueue slow functions into the thread pool, if the parallel run is enabled.
Aaron Huang24d215d2022-04-27 18:51:16 +08001717 std::future<std::string> dump_hals, dump_incident_report, dump_board, dump_checkins,
Kean Mariottica20f2d2023-12-15 09:34:25 +00001718 dump_netstats_report;
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001719 if (ds.dump_pool_) {
1720 // Pool was shutdown in DumpstateDefaultAfterCritical method in order to
Kean Mariotti306633e2022-09-05 16:30:47 +00001721 // drop root user. Restarts it.
1722 ds.dump_pool_->start(/* thread_counts = */3);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001723
Chris Morinbc223142022-02-04 14:17:11 -08001724 dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
1725 dump_incident_report = ds.dump_pool_->enqueueTask(
1726 DUMP_INCIDENT_REPORT_TASK, &DumpIncidentReport);
Aaron Huang24d215d2022-04-27 18:51:16 +08001727 dump_netstats_report = ds.dump_pool_->enqueueTask(
1728 DUMP_NETSTATS_PROTO_TASK, &DumpNetstatsProto);
Chris Morinbc223142022-02-04 14:17:11 -08001729 dump_board = ds.dump_pool_->enqueueTaskWithFd(
1730 DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
1731 dump_checkins = ds.dump_pool_->enqueueTaskWithFd(DUMP_CHECKINS_TASK, &DumpCheckins, _1);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001732 }
1733
Nandana Dutt5c390032019-03-12 10:52:56 +00001734 // Dump various things. Note that anything that takes "long" (i.e. several seconds) should
1735 // check intermittently (if it's intrerruptable like a foreach on pids) and/or should be wrapped
1736 // in a consent check (via RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK).
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001737 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001738 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001739 DumpBlockStatFiles();
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001740 DumpFile("MEMORY INFO", "/proc/meminfo");
1741 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001742 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001743
Kevin Jeon947922b2022-09-21 00:29:18 +00001744 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "BUGREPORT_PROCDUMP", {"bugreport_procdump"},
1745 CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001746
Sunny Goyal35949782019-11-19 15:54:36 -08001747 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpVisibleWindowViews);
1748
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001749 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1750 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1751 DumpFile("SLAB INFO", "/proc/slabinfo");
1752 DumpFile("ZONEINFO", "/proc/zoneinfo");
1753 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1754 DumpFile("BUDDYINFO", "/proc/buddyinfo");
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001755 DumpExternalFragmentationInfo();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001756
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001757 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001758
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001759 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001760 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001761
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001762 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001763 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_hals));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001764 } else {
1765 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_HALS_TASK, DumpHals);
1766 }
Steven Moreland81b429e2017-01-31 19:50:46 -08001767
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001768 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001769 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001770 struct stat s;
1771 if (stat("/proc/modules", &s) != 0) {
1772 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1773 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001774 RunCommand("LSMOD", {"lsmod"});
Woody Linc198f252021-05-04 16:37:11 +08001775 RunCommand("MODULES INFO",
1776 {"sh", "-c", "cat /proc/modules | cut -d' ' -f1 | "
1777 " while read MOD ; do echo modinfo:$MOD ; modinfo $MOD ; "
1778 "done"}, CommandOptions::AS_ROOT);
Felipe Lemee4eca582016-06-10 17:48:08 -07001779 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001780
Tom Cherryb87dbfa2020-07-28 11:28:53 -07001781 if (android::base::GetBoolProperty("ro.logd.kernel", false)) {
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001782 DoKernelLogcat();
1783 } else {
1784 do_dmesg();
1785 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001786
Devin Moore8df81bb2022-06-08 22:47:02 +00001787 DumpVintf();
1788
Felipe Lemef0292972016-11-22 13:57:05 -08001789 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001790
Jeff Brown1dc94e32014-09-11 14:15:27 -07001791 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001792 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001793
Jack Yu5a6b2e22020-08-14 18:13:35 +08001794 /* Dump Nfc NCI logs */
1795 ds.AddDir("/data/misc/nfc/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001796
Paul Chang0d2aad72020-02-13 20:04:03 +08001797 if (ds.options_->do_screenshot && !ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001798 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001799 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001800 }
1801
Felipe Lemee184f662016-10-27 10:04:47 -07001802 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001803
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001804 MaybeAddSystemTraceToZip();
1805
Narayan Kamath8f788292017-05-25 13:20:39 +01001806 // NOTE: tombstones are always added as separate entries in the zip archive
1807 // and are not interspersed with the main report.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001808 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
Narayan Kamathbd863722017-06-01 18:50:12 +01001809 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001810 if (!tombstones_dumped) {
1811 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001812 }
1813
Jayachandran Ca94c7172017-06-10 15:08:12 -07001814 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001815
Lorenzo Colitti807f2dd2022-05-27 12:48:37 +09001816 RunDumpsys("EBPF MAP STATS", {"connectivity", "trafficcontroller"});
Chenbo Feng276a3b62018-08-07 11:44:49 -07001817
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001818 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001819
Alessio Balsini9e332a72024-12-10 15:31:57 +00001820 DumpKernelMemoryAllocations();
1821
Woody Lin20767a92022-11-29 15:50:24 +08001822 DumpShutdownCheckpoints();
1823
Jayachandran Ca94c7172017-06-10 15:08:12 -07001824 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001825
1826 dump_route_tables();
1827
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001828 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1829 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1830 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001831
Nandana Dutt5c390032019-03-12 10:52:56 +00001832 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysHigh);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001833
Chiachang Wang668ede42021-05-17 17:14:20 +08001834 // The dump mechanism in connectivity is refactored due to modularization work. Connectivity can
1835 // only register with a default priority(NORMAL priority). Dumpstate has to call connectivity
1836 // dump with priority parameters to dump high priority information.
1837 RunDumpsys("SERVICE HIGH connectivity", {"connectivity", "--dump-priority", "HIGH"},
1838 CommandOptions::WithTimeout(10).Build());
1839
Elliott Hughes23ccc622017-02-28 10:14:22 -08001840 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001841
Joe Onoratod38bc3a2023-06-29 15:48:28 -07001842 DumpFile("SYSTEM BUILD-TIME RELEASE FLAGS", "/system/etc/build_flags.json");
1843 DumpFile("SYSTEM_EXT BUILD-TIME RELEASE FLAGS", "/system_ext/etc/build_flags.json");
1844 DumpFile("PRODUCT BUILD-TIME RELEASE FLAGS", "/product/etc/build_flags.json");
1845 DumpFile("VENDOR BUILD-TIME RELEASE FLAGS", "/vendor/etc/build_flags.json");
1846
Ted Bauerf6d61b82024-09-13 19:57:19 +00001847 RunCommand("ACONFIG FLAGS DUMP", {AFLAGS, "list"},
1848 CommandOptions::WithTimeout(10).Always().AsRootIfAvailable().Build());
Joe Onoratod38bc3a2023-06-29 15:48:28 -07001849
Jin Qianf334d662017-10-10 14:41:37 -07001850 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001851
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001852 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001853
Colin Crossf45fa6b2012-03-26 12:38:26 -07001854 /* Binder state is expensive to look at as it uses a lot of memory. */
Hridya Valsaraju920ba712020-02-09 16:27:01 -08001855 std::string binder_logs_dir = access("/dev/binderfs/binder_logs", R_OK) ?
1856 "/sys/kernel/debug/binder" : "/dev/binderfs/binder_logs";
1857
1858 DumpFile("BINDER FAILED TRANSACTION LOG", binder_logs_dir + "/failed_transaction_log");
1859 DumpFile("BINDER TRANSACTION LOG", binder_logs_dir + "/transaction_log");
1860 DumpFile("BINDER TRANSACTIONS", binder_logs_dir + "/transactions");
1861 DumpFile("BINDER STATS", binder_logs_dir + "/stats");
1862 DumpFile("BINDER STATE", binder_logs_dir + "/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001863
Yifan Hongd90cc652020-02-08 16:52:02 -08001864 ds.AddDir(SNAPSHOTCTL_LOG_DIR, false);
1865
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001866 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001867 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_board));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001868 } else {
1869 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
1870 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001871
Steven Moreland7440ddb2016-12-15 16:13:39 -08001872 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001873 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1874 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001875 // su does not exist on user builds, so try running without it.
1876 // This way any implementations of vril-dump that do not require
1877 // root can run on user builds.
1878 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001879 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001880 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001881 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001882 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001883 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001884 }
1885
Radud0776152024-10-29 12:08:54 +00001886 /* Dump USB information */
1887 RunCommand("typec_connector_class", {"typec_connector_class"},
1888 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
1889 RunCommand("lsusb", {"lsusb"}, CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
1890
Felipe Lemed8b94e52016-12-08 10:21:44 -08001891 printf("========================================================\n");
1892 printf("== Android Framework Services\n");
1893 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001894
Nandana Dutt5c390032019-03-12 10:52:56 +00001895 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001896
Jack He91ff2fe2021-02-18 18:23:43 -08001897 /* Dump Bluetooth HCI logs after getting bluetooth_manager dumpsys */
1898 ds.AddDir("/data/misc/bluetooth/logs", true);
1899
Rhed Jaoe017f982020-07-21 17:58:41 +08001900 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001901 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_checkins));
Rhed Jaoe017f982020-07-21 17:58:41 +08001902 } else {
1903 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_CHECKINS_TASK, DumpCheckins);
1904 }
Dianne Hackborn02bea972013-06-26 18:59:09 -07001905
Rhed Jaoc5f7ec32020-12-22 22:11:08 +08001906 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpAppInfos);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001907
Adrian Roos8b397ab2017-04-04 16:35:44 -07001908 printf("========================================================\n");
1909 printf("== Dropbox crashes\n");
1910 printf("========================================================\n");
1911
1912 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1913 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1914
Felipe Lemed8b94e52016-12-08 10:21:44 -08001915 printf("========================================================\n");
1916 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1917 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1918 printf("========================================================\n");
1919 printf("== dumpstate: done (id %d)\n", ds.id_);
1920 printf("========================================================\n");
Bookatz38472142018-09-28 10:20:24 -07001921
1922 printf("========================================================\n");
1923 printf("== Obtaining statsd metadata\n");
1924 printf("========================================================\n");
1925 // This differs from the usual dumpsys stats, which is the stats report data.
1926 RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
Mike Ma5c267872019-08-21 11:31:34 -07001927
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +09001928 // Add linker configuration directory
1929 ds.AddDir(LINKERCONFIG_DIR, true);
1930
Li Li830179f2022-01-04 12:53:29 -08001931 /* Dump frozen cgroupfs */
1932 dump_frozen_cgroupfs();
Li Li2eedd412021-06-30 15:11:53 -07001933
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001934 if (ds.dump_pool_) {
Aaron Huang24d215d2022-04-27 18:51:16 +08001935 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_netstats_report));
1936 } else {
1937 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_NETSTATS_PROTO_TASK,
1938 DumpNetstatsProto);
1939 }
1940
1941 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001942 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_incident_report));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001943 } else {
1944 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_INCIDENT_REPORT_TASK,
1945 DumpIncidentReport);
1946 }
Mike Ma5c267872019-08-21 11:31:34 -07001947
Kean Mariotti306633e2022-09-05 16:30:47 +00001948 MaybeAddUiTracesToZip();
1949
Nandana Dutt5c390032019-03-12 10:52:56 +00001950 return Dumpstate::RunStatus::OK;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001951}
1952
Nandana Dutt5c390032019-03-12 10:52:56 +00001953/*
1954 * Dumps state for the default case; drops root after it's no longer necessary.
1955 *
1956 * Returns RunStatus::OK if everything went fine.
1957 * Returns RunStatus::ERROR if there was an error.
1958 * Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport
1959 * with the caller.
1960 */
Jichao Lie89d9c12019-11-21 19:02:51 -08001961Dumpstate::RunStatus Dumpstate::DumpstateDefaultAfterCritical() {
Nandana Duttdb379fa2019-10-09 16:54:41 +01001962 // Capture first logcat early on; useful to take a snapshot before dumpstate logs take over the
1963 // buffer.
1964 DoLogcat();
1965 // Capture timestamp after first logcat to use in next logcat
1966 time_t logcat_ts = time(nullptr);
1967
Nandana Dutt4be45d12018-09-26 15:04:23 +01001968 /* collect stack traces from Dalvik and native processes (needs root) */
Chris Morinbc223142022-02-04 14:17:11 -08001969 std::future<std::string> dump_traces;
Rhed Jao5377d792020-07-16 17:37:39 +08001970 if (dump_pool_) {
1971 RETURN_IF_USER_DENIED_CONSENT();
1972 // One thread is enough since we only need to enqueue DumpTraces here.
1973 dump_pool_->start(/* thread_counts = */1);
1974
1975 // DumpTraces takes long time, post it to the another thread in the
1976 // pool, if pool is available
Chris Morinbc223142022-02-04 14:17:11 -08001977 dump_traces = dump_pool_->enqueueTask(
1978 DUMP_TRACES_TASK, &Dumpstate::DumpTraces, &ds, &dump_traces_path);
Rhed Jao5377d792020-07-16 17:37:39 +08001979 } else {
1980 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_TRACES_TASK, ds.DumpTraces,
1981 &dump_traces_path);
1982 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001983
1984 /* Run some operations that require root. */
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001985 if (!PropertiesHelper::IsDryRun()) {
Chris Morinc2cba7a2022-02-01 17:06:50 -08001986 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX);
1987 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX);
Andy Hungd62f7e62024-01-11 15:47:52 -08001988 ds.anr_trace_data_ = GetDumpFds(ANR_DIR, ANR_TRACE_FILE_PREFIX);
Woody Lin20767a92022-11-29 15:50:24 +08001989 ds.shutdown_checkpoints_ = GetDumpFds(
1990 SHUTDOWN_CHECKPOINTS_DIR, SHUTDOWN_CHECKPOINTS_FILE_PREFIX);
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001991 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001992
1993 ds.AddDir(RECOVERY_DIR, true);
1994 ds.AddDir(RECOVERY_DATA_DIR, true);
1995 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
Kelvin Zhang6eaa0f92022-09-12 09:29:19 -07001996 ds.AddDir(UPDATE_ENGINE_PREF_DIR, true);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001997 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1998 if (!PropertiesHelper::IsUserBuild()) {
1999 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
2000 ds.AddDir(PROFILE_DATA_DIR_REF, true);
Calin Juravlef84d3692020-04-28 15:31:12 -07002001 ds.AddZipEntry(ZIP_ROOT_DIR + PACKAGE_DEX_USE_LIST, PACKAGE_DEX_USE_LIST);
Nandana Dutt4be45d12018-09-26 15:04:23 +01002002 }
Jerry Changa1df8a92020-01-02 16:03:39 +08002003 ds.AddDir(PREREBOOT_DATA_DIR, false);
Nandana Dutt4be45d12018-09-26 15:04:23 +01002004 add_mountinfo();
Peter Collingbourne78aa2942023-02-15 14:50:31 -08002005 for (const char* path : {"/proc/cpuinfo", "/proc/meminfo"}) {
2006 ds.AddZipEntry(ZIP_ROOT_DIR + path, path);
2007 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01002008 DumpIpTablesAsRoot();
David Andersond9ba4752018-12-11 18:26:59 -08002009 DumpDynamicPartitionInfo();
Yifan Hong3945e1b2019-10-29 12:59:23 -07002010 ds.AddDir(OTA_METADATA_DIR, true);
Jeff Sharkey9df29d52023-02-06 14:26:30 -07002011 if (!PropertiesHelper::IsUserBuild()) {
2012 // Include dropbox entry files inside ZIP, but exclude
2013 // noisy WTF and StrictMode entries
2014 dump_files("", DROPBOX_DIR, skip_wtf_strictmode, _add_file_from_fd);
2015 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01002016
Benedict Wong8f9d8a42019-01-03 16:19:38 -08002017 // Capture any IPSec policies in play. No keys are exposed here.
Nandana Dutt4be45d12018-09-26 15:04:23 +01002018 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
2019
Benedict Wong8f9d8a42019-01-03 16:19:38 -08002020 // Dump IPsec stats. No keys are exposed here.
2021 DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
2022
Nandana Dutt4be45d12018-09-26 15:04:23 +01002023 // Run ss as root so we can see socket marks.
2024 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
2025
2026 // Run iotop as root to show top 100 IO threads
2027 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
2028
Erick Reyese68df822019-02-11 14:46:36 -08002029 // Gather shared memory buffer info if the product implements it
Hridya Valsaraju1da80c52021-01-09 22:10:11 -08002030 RunCommand("Dmabuf dump", {"dmabuf_dump"});
2031 RunCommand("Dmabuf per-buffer/per-exporter/per-device stats", {"dmabuf_dump", "-b"});
Erick Reyese68df822019-02-11 14:46:36 -08002032
Minchan Kim22c6a1e2019-09-30 15:58:10 -07002033 DumpFile("PSI cpu", "/proc/pressure/cpu");
2034 DumpFile("PSI memory", "/proc/pressure/memory");
2035 DumpFile("PSI io", "/proc/pressure/io");
2036
Steven Moreland9379c462023-12-21 02:04:27 +00002037 ds.AddZipEntry(ZIP_ROOT_DIR + KERNEL_CONFIG, KERNEL_CONFIG);
2038
MÃ¥rten Kongstad60195a72022-09-20 14:14:20 +02002039 RunCommand("SDK EXTENSIONS", {SDK_EXT_INFO, "--dump"},
2040 CommandOptions::WithTimeout(10).Always().DropRoot().Build());
2041
Nattharat Jariyanuntanaetb250cae2024-05-15 07:48:19 +00002042 // Dump UWB UCI logs here because apexdata requires root access
2043 ds.AddDir(UWB_LOG_DIR, true);
2044
Rhed Jao5377d792020-07-16 17:37:39 +08002045 if (dump_pool_) {
2046 RETURN_IF_USER_DENIED_CONSENT();
Chris Morinbc223142022-02-04 14:17:11 -08002047 WaitForTask(std::move(dump_traces));
Rhed Jao5377d792020-07-16 17:37:39 +08002048
Chris Morinbc223142022-02-04 14:17:11 -08002049 // Current running thread in the pool is the root user also. Delete
2050 // the pool and make a new one later to ensure none of threads in the pool are root.
2051 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao5377d792020-07-16 17:37:39 +08002052 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01002053 if (!DropRootUser()) {
Nandana Dutt5c390032019-03-12 10:52:56 +00002054 return Dumpstate::RunStatus::ERROR;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002055 }
2056
Nandana Dutt5c390032019-03-12 10:52:56 +00002057 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttdb379fa2019-10-09 16:54:41 +01002058 Dumpstate::RunStatus status = dumpstate();
2059 // Capture logcat since the last time we did it.
2060 DoSystemLogcat(logcat_ts);
2061 return status;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002062}
2063
Rhed Jaob5685b32020-08-14 17:19:17 +08002064// Common states for telephony and wifi which are needed to be collected before
2065// dumpstate drop the root user.
2066static void DumpstateRadioAsRoot() {
2067 DumpIpTablesAsRoot();
2068 ds.AddDir(LOGPERSIST_DATA_DIR, false);
2069}
2070
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002071// This method collects common dumpsys for telephony and wifi. Typically, wifi
2072// reports are fine to include all information, but telephony reports on user
2073// builds need to strip some content (see DumpstateTelephonyOnly).
2074static void DumpstateRadioCommon(bool include_sensitive_info = true) {
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002075 // We need to be picky about some stuff for telephony reports on user builds.
2076 if (!include_sensitive_info) {
2077 // Only dump the radio log buffer (other buffers and dumps contain too much unrelated info).
2078 DoRadioLogcat();
2079 } else {
Rhed Jaob5685b32020-08-14 17:19:17 +08002080 // DumpHals takes long time, post it to the another thread in the pool,
2081 // if pool is available.
Chris Morinbc223142022-02-04 14:17:11 -08002082 std::future<std::string> dump_hals;
Rhed Jaob5685b32020-08-14 17:19:17 +08002083 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002084 dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
Rhed Jaob5685b32020-08-14 17:19:17 +08002085 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002086 // Contains various system properties and process startup info.
2087 do_dmesg();
2088 // Logs other than the radio buffer may contain package/component names and potential PII.
2089 DoLogcat();
2090 // Too broad for connectivity problems.
2091 DoKmsg();
Rhed Jaob5685b32020-08-14 17:19:17 +08002092 // DumpHals contains unrelated hardware info (camera, NFC, biometrics, ...).
2093 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002094 WaitForTask(std::move(dump_hals));
Rhed Jaob5685b32020-08-14 17:19:17 +08002095 } else {
2096 RUN_SLOW_FUNCTION_AND_LOG(DUMP_HALS_TASK, DumpHals);
2097 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002098 }
2099
Jayachandran Ca94c7172017-06-10 15:08:12 -07002100 DumpPacketStats();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002101 DumpIpAddrAndRules();
2102 dump_route_tables();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002103 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
2104 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08002105}
2106
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002107// We use "telephony" here for legacy reasons, though this now really means "connectivity" (cellular
2108// + wifi + networking). This method collects dumpsys for connectivity debugging only. General rules
2109// for what can be included on user builds: all reported information MUST directly relate to
2110// connectivity debugging or customer support and MUST NOT contain unrelated personally identifiable
2111// information. This information MUST NOT identify user-installed packages (UIDs are OK, package
2112// names are not), and MUST NOT contain logs of user application traffic.
2113// TODO(b/148168577) rename this and other related fields/methods to "connectivity" instead.
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08002114static void DumpstateTelephonyOnly(const std::string& calling_package) {
mukesh agrawal253dad42018-01-23 21:59:59 -08002115 DurationReporter duration_reporter("DUMPSTATE");
Jichao Lie89d9c12019-11-21 19:02:51 -08002116
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002117 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
mukesh agrawal253dad42018-01-23 21:59:59 -08002118
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002119 const bool include_sensitive_info = !PropertiesHelper::IsUserBuild();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002120
Rhed Jaob5685b32020-08-14 17:19:17 +08002121 DumpstateRadioAsRoot();
2122 if (!DropRootUser()) {
2123 return;
2124 }
2125
2126 // Starts thread pool after the root user is dropped, and two additional threads
2127 // are created for DumpHals in the DumpstateRadioCommon and DumpstateBoard.
Chris Morinbc223142022-02-04 14:17:11 -08002128 std::future<std::string> dump_board;
Rhed Jaob5685b32020-08-14 17:19:17 +08002129 if (ds.dump_pool_) {
2130 ds.dump_pool_->start(/*thread_counts =*/2);
2131
2132 // DumpstateBoard takes long time, post it to the another thread in the pool,
2133 // if pool is available.
Chris Morinbc223142022-02-04 14:17:11 -08002134 dump_board = ds.dump_pool_->enqueueTaskWithFd(
2135 DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
Rhed Jaob5685b32020-08-14 17:19:17 +08002136 }
2137
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002138 DumpstateRadioCommon(include_sensitive_info);
2139
2140 if (include_sensitive_info) {
2141 // Contains too much unrelated PII, and given the unstructured nature of sysprops, we can't
2142 // really cherrypick all of the connectivity-related ones. Apps generally have no business
2143 // reading these anyway, and there should be APIs to supply the info in a more app-friendly
2144 // way.
2145 RunCommand("SYSTEM PROPERTIES", {"getprop"});
2146 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002147
2148 printf("========================================================\n");
2149 printf("== Android Framework Services\n");
2150 printf("========================================================\n");
2151
Vishnu Nair652cc802017-11-30 15:18:30 -08002152 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2153 SEC_TO_MSEC(10));
Hunter Knepshield31cbae12021-05-11 16:23:24 -07002154 RunDumpsys("DUMPSYS", {"vcn_management"}, CommandOptions::WithTimeout(90).Build(),
2155 SEC_TO_MSEC(10));
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08002156 if (include_sensitive_info) {
2157 // Carrier apps' services will be dumped below in dumpsys activity service all-non-platform.
2158 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
2159 SEC_TO_MSEC(10));
2160 } else {
2161 // If the caller is a carrier app and has a carrier service, dump it here since we aren't
2162 // running dumpsys activity service all-non-platform below. Due to the increased output, we
2163 // give a higher timeout as well.
2164 RunDumpsys("DUMPSYS", {"carrier_config", "--requesting-package", calling_package},
2165 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(30));
2166 }
2167 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002168 RunDumpsys("DUMPSYS", {"netpolicy"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2169 RunDumpsys("DUMPSYS", {"network_management"}, CommandOptions::WithTimeout(90).Build(),
Sooraj Sasindrane8d98912018-04-20 11:31:55 -07002170 SEC_TO_MSEC(10));
Hunter Knepshield0fe51b12020-03-05 16:58:20 -08002171 RunDumpsys("DUMPSYS", {"telephony.registry"}, CommandOptions::WithTimeout(90).Build(),
2172 SEC_TO_MSEC(10));
Jack Yu773cc032023-03-16 22:43:39 -07002173 RunDumpsys("DUMPSYS", {"isub"}, CommandOptions::WithTimeout(90).Build(),
2174 SEC_TO_MSEC(10));
Grant Menke56698972023-02-24 13:11:07 -08002175 RunDumpsys("DUMPSYS", {"telecom"}, CommandOptions::WithTimeout(90).Build(),
2176 SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002177 if (include_sensitive_info) {
2178 // Contains raw IP addresses, omit from reports on user builds.
2179 RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2180 // Contains raw destination IP/MAC addresses, omit from reports on user builds.
2181 RunDumpsys("DUMPSYS", {"connmetrics"}, CommandOptions::WithTimeout(90).Build(),
2182 SEC_TO_MSEC(10));
2183 // Contains package/component names, omit from reports on user builds.
2184 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
2185 SEC_TO_MSEC(10));
2186 // Contains package names, but should be relatively simple to remove them (also contains
2187 // UIDs already), omit from reports on user builds.
2188 RunDumpsys("BATTERYSTATS", {"deviceidle"}, CommandOptions::WithTimeout(90).Build(),
2189 SEC_TO_MSEC(10));
2190 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002191
2192 printf("========================================================\n");
2193 printf("== Running Application Services\n");
2194 printf("========================================================\n");
2195
2196 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
2197
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002198 if (include_sensitive_info) {
2199 printf("========================================================\n");
2200 printf("== Running Application Services (non-platform)\n");
2201 printf("========================================================\n");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002202
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002203 // Contains package/component names and potential PII, omit from reports on user builds.
2204 // To get dumps of the active CarrierService(s) on user builds, we supply an argument to the
2205 // carrier_config dumpsys instead.
2206 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
2207 DUMPSYS_COMPONENTS_OPTIONS);
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002208
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002209 printf("========================================================\n");
2210 printf("== Checkins\n");
2211 printf("========================================================\n");
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002212
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002213 // Contains package/component names, omit from reports on user builds.
2214 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
2215 }
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002216
2217 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07002218 printf("== dumpstate: done (id %d)\n", ds.id_);
2219 printf("========================================================\n");
Rhed Jaob5685b32020-08-14 17:19:17 +08002220
2221 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002222 WaitForTask(std::move(dump_board));
Rhed Jaob5685b32020-08-14 17:19:17 +08002223 } else {
2224 RUN_SLOW_FUNCTION_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
2225 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002226}
2227
mukesh agrawal253dad42018-01-23 21:59:59 -08002228// This method collects dumpsys for wifi debugging only
2229static void DumpstateWifiOnly() {
2230 DurationReporter duration_reporter("DUMPSTATE");
2231
Rhed Jaob5685b32020-08-14 17:19:17 +08002232 DumpstateRadioAsRoot();
2233 if (!DropRootUser()) {
2234 return;
2235 }
2236
2237 // Starts thread pool after the root user is dropped. Only one additional
2238 // thread is needed for DumpHals in the DumpstateRadioCommon.
2239 if (ds.dump_pool_) {
2240 ds.dump_pool_->start(/*thread_counts =*/1);
2241 }
2242
mukesh agrawal253dad42018-01-23 21:59:59 -08002243 DumpstateRadioCommon();
2244
2245 printf("========================================================\n");
2246 printf("== Android Framework Services\n");
2247 printf("========================================================\n");
2248
2249 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2250 SEC_TO_MSEC(10));
2251 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
2252 SEC_TO_MSEC(10));
2253
2254 printf("========================================================\n");
2255 printf("== dumpstate: done (id %d)\n", ds.id_);
2256 printf("========================================================\n");
2257}
2258
Elis Elliott8e401ad2023-08-08 11:18:59 +00002259// Collects a lightweight dumpstate to be used for debugging onboarding related flows.
2260static void DumpstateOnboardingOnly() {
2261 ds.AddDir(LOGPERSIST_DATA_DIR, false);
2262}
2263
Christopher Ferris83e0e842024-05-31 13:13:34 -07002264static std::string GetTimestamp(const timespec& ts) {
2265 tm tm;
2266 localtime_r(&ts.tv_sec, &tm);
2267
2268 // Reserve enough space for the entire time string, includes the space
2269 // for the '\0' to make the calculations below easier by using size for
2270 // the total string size.
2271 std::string str(sizeof("1970-01-01 00:00:00.123456789+0830"), '\0');
2272 size_t n = strftime(str.data(), str.size(), "%F %H:%M", &tm);
2273 if (n == 0) {
2274 return "TIMESTAMP FAILURE";
2275 }
2276 int num_chars = snprintf(&str[n], str.size() - n, ":%02d.%09ld", tm.tm_sec, ts.tv_nsec);
2277 if (num_chars > str.size() - n) {
2278 return "TIMESTAMP FAILURE";
2279 }
2280 n += static_cast<size_t>(num_chars);
2281 if (strftime(&str[n], str.size() - n, "%z", &tm) == 0) {
2282 return "TIMESTAMP FAILURE";
2283 }
2284 return str;
2285}
2286
2287static std::string GetCmdline(pid_t pid) {
2288 std::string cmdline;
2289 if (!android::base::ReadFileToString(android::base::StringPrintf("/proc/%d/cmdline", pid),
2290 &cmdline)) {
2291 return "UNKNOWN";
2292 }
2293 // There are '\0' terminators between arguments, convert them to spaces.
2294 // But start by skipping all trailing '\0' values.
2295 size_t cur = cmdline.size() - 1;
2296 while (cur != 0 && cmdline[cur] == '\0') {
2297 cur--;
2298 }
2299 if (cur == 0) {
2300 return "UNKNOWN";
2301 }
2302 while ((cur = cmdline.rfind('\0', cur)) != std::string::npos) {
2303 cmdline[cur] = ' ';
2304 }
2305 return cmdline;
2306}
2307
2308static void DumpPidHeader(int fd, pid_t pid, const timespec& ts) {
2309 // For consistency, the header to this message matches the one
2310 // dumped by debuggerd.
2311 dprintf(fd, "\n----- pid %d at %s -----\n", pid, GetTimestamp(ts).c_str());
2312 dprintf(fd, "Cmd line: %s\n", GetCmdline(pid).c_str());
2313}
2314
2315static void DumpPidFooter(int fd, pid_t pid) {
2316 // For consistency, the footer to this message matches the one
2317 // dumped by debuggerd.
2318 dprintf(fd, "----- end %d -----\n", pid);
2319}
2320
2321static bool DumpBacktrace(int fd, pid_t pid, bool is_java_process) {
2322 int ret = dump_backtrace_to_file_timeout(
2323 pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace, 3, fd);
2324 if (ret == -1 && is_java_process) {
2325 // Tried to unwind as a java process, try a native unwind.
2326 dprintf(fd, "Java unwind failed for pid %d, trying a native unwind.\n", pid);
2327 ret = dump_backtrace_to_file_timeout(pid, kDebuggerdNativeBacktrace, 3, fd);
2328 }
2329 return ret != -1;
2330}
2331
Nandana Duttcf419a72019-03-14 10:40:17 +00002332Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
Gavin Corkery789d7a52021-02-24 23:52:35 +00002333 const std::string temp_file_pattern = ds.bugreport_internal_dir_ + "/dumptrace_XXXXXX";
Nandana Duttfaafd522019-03-11 09:23:09 +00002334 const size_t buf_size = temp_file_pattern.length() + 1;
2335 std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
2336 memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
2337
2338 // Create a new, empty file to receive all trace dumps.
2339 //
2340 // TODO: This can be simplified once we remove support for the old style
2341 // dumps. We can have a file descriptor passed in to dump_traces instead
2342 // of creating a file, closing it and then reopening it again.
2343 android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
2344 if (fd < 0) {
2345 MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002346 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002347 }
2348
2349 // Nobody should have access to this temporary file except dumpstate, but we
2350 // temporarily grant 'read' to 'others' here because this file is created
2351 // when tombstoned is still running as root, but dumped after dropping. This
2352 // can go away once support for old style dumping has.
2353 const int chmod_ret = fchmod(fd, 0666);
2354 if (chmod_ret < 0) {
2355 MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002356 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002357 }
2358
2359 std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
2360 if (proc.get() == nullptr) {
2361 MYLOGE("opendir /proc failed: %s\n", strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002362 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002363 }
2364
2365 // Number of times process dumping has timed out. If we encounter too many
2366 // failures, we'll give up.
2367 int timeout_failures = 0;
2368 bool dalvik_found = false;
2369
Jayant Chowdharya0a8eb22022-05-20 03:30:09 +00002370 const std::set<int> hal_pids = get_interesting_pids();
Nandana Duttfaafd522019-03-11 09:23:09 +00002371
2372 struct dirent* d;
2373 while ((d = readdir(proc.get()))) {
Nandana Duttcf419a72019-03-14 10:40:17 +00002374 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttfaafd522019-03-11 09:23:09 +00002375 int pid = atoi(d->d_name);
2376 if (pid <= 0) {
2377 continue;
2378 }
2379
2380 const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
2381 std::string exe;
2382 if (!android::base::Readlink(link_name, &exe)) {
2383 continue;
2384 }
2385
2386 bool is_java_process;
2387 if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
2388 // Don't bother dumping backtraces for the zygote.
2389 if (IsZygote(pid)) {
2390 continue;
2391 }
2392
2393 dalvik_found = true;
2394 is_java_process = true;
2395 } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
2396 is_java_process = false;
2397 } else {
2398 // Probably a native process we don't care about, continue.
2399 continue;
2400 }
2401
2402 // If 3 backtrace dumps fail in a row, consider debuggerd dead.
2403 if (timeout_failures == 3) {
2404 dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
2405 break;
2406 }
2407
Christopher Ferris83e0e842024-05-31 13:13:34 -07002408 timespec start_timespec;
2409 clock_gettime(CLOCK_REALTIME, &start_timespec);
2410 if (IsCached(pid)) {
2411 DumpPidHeader(fd, pid, start_timespec);
2412 dprintf(fd, "Process is cached, skipping backtrace due to high chance of timeout.\n");
2413 DumpPidFooter(fd, pid);
2414 continue;
2415 }
Nandana Duttfaafd522019-03-11 09:23:09 +00002416
Christopher Ferris83e0e842024-05-31 13:13:34 -07002417 const uint64_t start = Nanotime();
2418 if (!DumpBacktrace(fd, pid, is_java_process)) {
2419 if (IsCached(pid)) {
2420 DumpPidHeader(fd, pid, start_timespec);
2421 dprintf(fd, "Backtrace failed, but process has become cached.\n");
2422 DumpPidFooter(fd, pid);
2423 continue;
2424 }
2425
2426 DumpPidHeader(fd, pid, start_timespec);
2427 dprintf(fd, "Backtrace gathering failed, likely due to a timeout.\n");
2428 DumpPidFooter(fd, pid);
2429
2430 dprintf(fd, "\n[dump %s stack %d: %.3fs elapsed]\n",
2431 is_java_process ? "dalvik" : "native", pid,
2432 (float)(Nanotime() - start) / NANOS_PER_SEC);
Nandana Duttfaafd522019-03-11 09:23:09 +00002433 timeout_failures++;
2434 continue;
2435 }
2436
2437 // We've successfully dumped stack traces, reset the failure count
2438 // and write a summary of the elapsed time to the file and continue with the
2439 // next process.
2440 timeout_failures = 0;
2441
2442 dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
2443 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
2444 }
2445
2446 if (!dalvik_found) {
2447 MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
2448 }
2449
Nandana Duttcf419a72019-03-14 10:40:17 +00002450 *path = file_name_buf.release();
2451 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002452}
2453
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002454static dumpstate_hal_hidl::DumpstateMode GetDumpstateHalModeHidl(
2455 const Dumpstate::BugreportMode bugreport_mode) {
2456 switch (bugreport_mode) {
2457 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2458 return dumpstate_hal_hidl::DumpstateMode::FULL;
2459 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2460 return dumpstate_hal_hidl::DumpstateMode::INTERACTIVE;
2461 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2462 return dumpstate_hal_hidl::DumpstateMode::REMOTE;
2463 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2464 return dumpstate_hal_hidl::DumpstateMode::WEAR;
2465 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2466 return dumpstate_hal_hidl::DumpstateMode::CONNECTIVITY;
2467 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2468 return dumpstate_hal_hidl::DumpstateMode::WIFI;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002469 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002470 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2471 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2472 }
2473 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2474}
2475
2476static dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode GetDumpstateHalModeAidl(
2477 const Dumpstate::BugreportMode bugreport_mode) {
2478 switch (bugreport_mode) {
2479 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2480 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::FULL;
2481 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2482 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::INTERACTIVE;
2483 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2484 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::REMOTE;
2485 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2486 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WEAR;
2487 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2488 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::CONNECTIVITY;
2489 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2490 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WIFI;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002491 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002492 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2493 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2494 }
2495 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2496}
2497
Steven Moreland0d564d52025-01-10 22:24:57 +00002498// BAD - See README.md: "Dumpstate philosophy: exec not link"
2499// This should all be moved into a separate binary rather than have complex logic here.
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002500static void DoDumpstateBoardHidl(
2501 const sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_1_0,
2502 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2503 const Dumpstate::BugreportMode bugreport_mode,
2504 const size_t timeout_sec) {
2505
2506 using ScopedNativeHandle =
2507 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
2508 ScopedNativeHandle handle(native_handle_create(static_cast<int>(dumpstate_fds.size()), 0),
2509 [](native_handle_t* handle) {
2510 // we don't close file handle's here
2511 // via native_handle_close(handle)
2512 // instead we let dumpstate_fds close the file handles when
2513 // dumpstate_fds gets destroyed
2514 native_handle_delete(handle);
2515 });
2516 if (handle == nullptr) {
2517 MYLOGE("Could not create native_handle for dumpstate HAL\n");
2518 return;
2519 }
2520
2521 for (size_t i = 0; i < dumpstate_fds.size(); i++) {
2522 handle.get()->data[i] = dumpstate_fds[i].get();
2523 }
2524
2525 // Prefer version 1.1 if available. New devices launching with R are no longer allowed to
2526 // implement just 1.0.
2527 const char* descriptor_to_kill;
2528 using DumpstateBoardTask = std::packaged_task<bool()>;
2529 DumpstateBoardTask dumpstate_board_task;
2530 sp<dumpstate_hal_hidl::IDumpstateDevice> dumpstate_hal(
2531 dumpstate_hal_hidl::IDumpstateDevice::castFrom(dumpstate_hal_1_0));
2532 if (dumpstate_hal != nullptr) {
2533 MYLOGI("Using IDumpstateDevice v1.1 HIDL HAL");
2534
2535 dumpstate_hal_hidl::DumpstateMode dumpstate_hal_mode =
2536 GetDumpstateHalModeHidl(bugreport_mode);
2537
2538 descriptor_to_kill = dumpstate_hal_hidl::IDumpstateDevice::descriptor;
2539 dumpstate_board_task =
2540 DumpstateBoardTask([timeout_sec, dumpstate_hal_mode, dumpstate_hal, &handle]() -> bool {
2541 ::android::hardware::Return<dumpstate_hal_hidl::DumpstateStatus> status =
2542 dumpstate_hal->dumpstateBoard_1_1(handle.get(), dumpstate_hal_mode,
2543 SEC_TO_MSEC(timeout_sec));
2544 if (!status.isOk()) {
2545 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2546 return false;
2547 } else if (status != dumpstate_hal_hidl::DumpstateStatus::OK) {
2548 MYLOGE("dumpstateBoard failed with DumpstateStatus::%s\n",
2549 dumpstate_hal_hidl::toString(status).c_str());
2550 return false;
2551 }
2552 return true;
2553 });
2554 } else {
2555 MYLOGI("Using IDumpstateDevice v1.0 HIDL HAL");
2556
2557 descriptor_to_kill = dumpstate_hal_hidl_1_0::IDumpstateDevice::descriptor;
2558 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal_1_0, &handle]() -> bool {
2559 ::android::hardware::Return<void> status =
2560 dumpstate_hal_1_0->dumpstateBoard(handle.get());
2561 if (!status.isOk()) {
2562 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2563 return false;
2564 }
2565 return true;
2566 });
2567 }
2568 auto result = dumpstate_board_task.get_future();
2569 std::thread(std::move(dumpstate_board_task)).detach();
2570
2571 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2572 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2573 if (!android::base::SetProperty(
2574 "ctl.interface_restart",
2575 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2576 MYLOGE("Couldn't restart dumpstate HAL\n");
2577 }
2578 }
2579 // Wait some time for init to kill dumpstate vendor HAL
2580 constexpr size_t killing_timeout_sec = 10;
2581 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2582 MYLOGE(
2583 "killing dumpstateBoard timed out after %zus, continue and "
2584 "there might be racing in content\n",
2585 killing_timeout_sec);
2586 }
2587}
2588
2589static void DoDumpstateBoardAidl(
2590 const std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal,
2591 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2592 const Dumpstate::BugreportMode bugreport_mode, const size_t timeout_sec) {
2593 MYLOGI("Using IDumpstateDevice AIDL HAL");
2594
2595 const char* descriptor_to_kill;
2596 using DumpstateBoardTask = std::packaged_task<bool()>;
2597 DumpstateBoardTask dumpstate_board_task;
2598 dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode dumpstate_hal_mode =
2599 GetDumpstateHalModeAidl(bugreport_mode);
2600
2601 descriptor_to_kill = dumpstate_hal_aidl::IDumpstateDevice::descriptor;
2602 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal, &dumpstate_fds, dumpstate_hal_mode,
2603 timeout_sec]() -> bool {
2604 auto status = dumpstate_hal->dumpstateBoard(dumpstate_fds, dumpstate_hal_mode, timeout_sec);
2605
2606 if (!status.isOk()) {
2607 MYLOGE("dumpstateBoard failed: %s\n", status.getDescription().c_str());
2608 return false;
2609 }
2610 return true;
2611 });
2612 auto result = dumpstate_board_task.get_future();
2613 std::thread(std::move(dumpstate_board_task)).detach();
2614
2615 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2616 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2617 if (!android::base::SetProperty(
2618 "ctl.interface_restart",
2619 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2620 MYLOGE("Couldn't restart dumpstate HAL\n");
2621 }
2622 }
2623 // Wait some time for init to kill dumpstate vendor HAL
2624 constexpr size_t killing_timeout_sec = 10;
2625 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2626 MYLOGE(
2627 "killing dumpstateBoard timed out after %zus, continue and "
2628 "there might be racing in content\n",
2629 killing_timeout_sec);
2630 }
2631}
2632
2633static std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> GetDumpstateBoardAidlService() {
2634 const std::string aidl_instance_name =
2635 std::string(dumpstate_hal_aidl::IDumpstateDevice::descriptor) + "/default";
2636
2637 if (!AServiceManager_isDeclared(aidl_instance_name.c_str())) {
2638 return nullptr;
2639 }
2640
2641 ndk::SpAIBinder dumpstateBinder(AServiceManager_waitForService(aidl_instance_name.c_str()));
2642
2643 return dumpstate_hal_aidl::IDumpstateDevice::fromBinder(dumpstateBinder);
2644}
2645
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002646void Dumpstate::DumpstateBoard(int out_fd) {
2647 dprintf(out_fd, "========================================================\n");
2648 dprintf(out_fd, "== Board\n");
2649 dprintf(out_fd, "========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08002650
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002651 /*
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002652 * mount debugfs for non-user builds with ro.product.debugfs_restrictions.enabled
Hridya Valsaraju51101602021-04-02 14:32:46 -07002653 * set to true and unmount it after invoking dumpstateBoard_* methods.
2654 * This is to enable debug builds to not have debugfs mounted during runtime.
2655 * It will also ensure that debugfs is only accessed by the dumpstate HAL.
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002656 */
Hridya Valsaraju51101602021-04-02 14:32:46 -07002657 auto mount_debugfs =
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002658 android::base::GetBoolProperty("ro.product.debugfs_restrictions.enabled", false);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002659 if (mount_debugfs) {
2660 RunCommand("mount debugfs", {"mount", "-t", "debugfs", "debugfs", "/sys/kernel/debug"},
2661 AS_ROOT_20);
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002662 RunCommand("chmod debugfs", {"chmod", "0755", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002663 }
2664
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002665 std::vector<std::string> paths;
2666 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07002667 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002668 paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
2669 kDumpstateBoardFiles[i].c_str()));
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002670 remover.emplace_back(android::base::make_scope_guard(
2671 std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002672 }
Jie Song9fbfad02017-06-20 16:29:42 -07002673
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002674 // get dumpstate HAL AIDL implementation
2675 std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal_handle_aidl(
2676 GetDumpstateBoardAidlService());
2677 if (dumpstate_hal_handle_aidl == nullptr) {
2678 MYLOGI("No IDumpstateDevice AIDL implementation\n");
2679 }
2680
2681 // get dumpstate HAL HIDL implementation, only if AIDL HAL implementation not found
2682 sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_handle_hidl_1_0 = nullptr;
2683 if (dumpstate_hal_handle_aidl == nullptr) {
2684 dumpstate_hal_handle_hidl_1_0 = dumpstate_hal_hidl_1_0::IDumpstateDevice::getService();
2685 if (dumpstate_hal_handle_hidl_1_0 == nullptr) {
2686 MYLOGI("No IDumpstateDevice HIDL implementation\n");
2687 }
2688 }
2689
2690 // if neither HIDL nor AIDL implementation found, then return
2691 if (dumpstate_hal_handle_hidl_1_0 == nullptr && dumpstate_hal_handle_aidl == nullptr) {
2692 MYLOGE("Could not find IDumpstateDevice implementation\n");
Wei Wang587eac92018-04-05 12:17:20 -07002693 return;
2694 }
2695
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002696 // this is used to hold the file descriptors and when this variable goes out of scope
2697 // the file descriptors are closed
2698 std::vector<::ndk::ScopedFileDescriptor> dumpstate_fds;
Wei Wang587eac92018-04-05 12:17:20 -07002699
Nandana Dutt5c390032019-03-12 10:52:56 +00002700 // TODO(128270426): Check for consent in between?
Wei Wang587eac92018-04-05 12:17:20 -07002701 for (size_t i = 0; i < paths.size(); i++) {
2702 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
2703
2704 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
2705 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
2706 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
2707 if (fd < 0) {
2708 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
2709 return;
2710 }
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002711
2712 dumpstate_fds.emplace_back(fd.release());
2713 // we call fd.release() here to make sure "fd" does not get closed
2714 // after "fd" goes out of scope after this block.
2715 // "fd" will be closed when "dumpstate_fds" goes out of scope
2716 // i.e. when we exit this function
Wei Wang587eac92018-04-05 12:17:20 -07002717 }
2718
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002719 // Given that bugreport is required to diagnose failures, it's better to set an arbitrary amount
2720 // of timeout for IDumpstateDevice than to block the rest of bugreport. In the timeout case, we
2721 // will kill the HAL and grab whatever it dumped in time.
Michael Eastwood8523ea02022-03-10 16:33:08 -08002722 constexpr size_t timeout_sec = 45;
Wei Wang587eac92018-04-05 12:17:20 -07002723
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002724 if (dumpstate_hal_handle_aidl != nullptr) {
2725 DoDumpstateBoardAidl(dumpstate_hal_handle_aidl, dumpstate_fds, options_->bugreport_mode,
2726 timeout_sec);
2727 } else if (dumpstate_hal_handle_hidl_1_0 != nullptr) {
2728 // run HIDL HAL only if AIDL HAL not found
2729 DoDumpstateBoardHidl(dumpstate_hal_handle_hidl_1_0, dumpstate_fds, options_->bugreport_mode,
2730 timeout_sec);
Wei Wang587eac92018-04-05 12:17:20 -07002731 }
2732
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002733 if (mount_debugfs) {
Hridya Valsaraju51101602021-04-02 14:32:46 -07002734 auto keep_debugfs_mounted =
2735 android::base::GetProperty("persist.dbg.keep_debugfs_mounted", "");
2736 if (keep_debugfs_mounted.empty())
2737 RunCommand("unmount debugfs", {"umount", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002738 }
2739
Wei Wang587eac92018-04-05 12:17:20 -07002740 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
2741 for (size_t i = 0; i < paths.size(); i++) {
2742 struct stat s;
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002743 if (fstat(dumpstate_fds[i].get(), &s) == -1) {
2744 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(), strerror(errno));
Wei Wang587eac92018-04-05 12:17:20 -07002745 file_sizes[i] = -1;
2746 continue;
2747 }
2748 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002749 }
2750
2751 for (size_t i = 0; i < paths.size(); i++) {
2752 if (file_sizes[i] == -1) {
2753 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002754 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002755 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07002756 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002757 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002758 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002759 remover[i].Disable();
2760 EnqueueAddZipEntryAndCleanupIfNeeded(kDumpstateBoardFiles[i], paths[i]);
2761 dprintf(out_fd, "*** See %s entry ***\n", kDumpstateBoardFiles[i].c_str());
Jie Song9fbfad02017-06-20 16:29:42 -07002762 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08002763}
2764
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002765static void ShowUsage() {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002766 fprintf(stderr,
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002767 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o directory] [-p] "
2768 "[-s] [-S] [-q] [-P] [-R] [-L] [-V version]\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002769 " -h: display this help message\n"
2770 " -b: play sound file instead of vibrate, at beginning of job\n"
2771 " -e: play sound file instead of vibrate, at end of job\n"
mhasank2d75c442020-06-11 15:05:25 -07002772 " -o: write to custom directory (only in limited mode)\n"
Abhijeet Kaurbb55a3b2019-06-13 18:07:25 +01002773 " -p: capture screenshot to filename.png\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002774 " -s: write zipped file to control socket (for init)\n"
2775 " -S: write file location to control socket (for init)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002776 " -q: disable vibrate\n"
Abhijeet Kaure370d682019-10-01 16:49:30 +01002777 " -P: send broadcast when started and do progress updates\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002778 " -R: take bugreport in remote mode (shouldn't be used with -P)\n"
Nandana Dutt235864b2019-01-22 12:10:16 +00002779 " -w: start binder service and make it wait for a call to startBugreport\n"
mhasankd451a472020-05-26 18:02:39 -07002780 " -L: output limited information that is safe for submission in feedback reports\n"
Felipe Lemed071c682016-10-20 16:48:00 -07002781 " -v: prints the dumpstate header and exit\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002782}
2783
Wei Liuf87959e2016-08-26 14:51:42 -07002784static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07002785 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07002786}
2787
Felipe Leme1d486fe2016-10-14 18:06:47 -07002788bool Dumpstate::FinishZipFile() {
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002789 // Runs all enqueued adding zip entry and cleanup tasks before finishing the zip file.
2790 if (zip_entry_tasks_) {
2791 zip_entry_tasks_->run(/* do_cancel = */false);
2792 }
2793
Felipe Leme9a523ae2016-10-20 15:10:33 -07002794 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07002795 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07002796 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002797 // Final timestamp
2798 char date[80];
2799 time_t the_real_now_please_stand_up = time(nullptr);
2800 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002801 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002802 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002803
Felipe Leme9a523ae2016-10-20 15:10:33 -07002804 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002805 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08002806 return false;
2807 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07002808 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002809 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08002810 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08002811 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08002812
Felipe Leme0f3fb202016-06-10 17:10:53 -07002813 // Add log file (which contains stderr output) to zip...
2814 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002815 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07002816 MYLOGE("Failed to add dumpstate log to .zip file\n");
2817 return false;
2818 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002819 // TODO: Should truncate the existing file.
2820 // ... and re-open it for further logging.
Nandana Dutta344cb62019-02-22 15:12:35 +00002821 if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
2822 return false;
2823 }
Felipe Leme0f3fb202016-06-10 17:10:53 -07002824 fprintf(stderr, "\n");
2825
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002826 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07002827 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002828 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002829 return false;
2830 }
2831
Felipe Leme1d486fe2016-10-14 18:06:47 -07002832 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
2833 ds.zip_file.reset(nullptr);
2834
Felipe Lemee9d2c542016-11-15 11:48:26 -08002835 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002836 android::os::UnlinkAndLogOnError(tmp_path_);
Felipe Lemec4eee562016-04-21 15:42:55 -07002837
Felipe Leme1e9edc62015-12-21 16:02:13 -08002838 return true;
2839}
Felipe Leme6e01fa62015-11-11 19:35:14 -08002840
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00002841static void SendBroadcast(const std::string& action,
2842 const std::vector<std::string>& args,
2843 int32_t user_id) {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002844 // clang-format off
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00002845 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user",
2846 std::to_string(user_id), "--receiver-foreground",
2847 "--receiver-include-background", "-a", action};
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002848 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08002849
2850 am.insert(am.end(), args.begin(), args.end());
2851
Felipe Leme8d2410e2017-02-08 09:46:08 -08002852 RunCommand("", am,
2853 CommandOptions::WithTimeout(20)
2854 .Log("Sending broadcast: '%s'\n")
2855 .Always()
2856 .DropRoot()
2857 .RedirectStderr()
2858 .Build());
2859}
2860
Felipe Leme35b8cf12017-02-10 15:47:29 -08002861static void Vibrate(int duration_ms) {
2862 // clang-format off
Lais Andrade51156962021-02-22 19:21:35 +00002863 std::vector<std::string> args = {"cmd", "vibrator_manager", "synced", "-f", "-d", "dumpstate",
2864 "oneshot", std::to_string(duration_ms)};
2865 RunCommand("", args,
Felipe Leme35b8cf12017-02-10 15:47:29 -08002866 CommandOptions::WithTimeout(10)
2867 .Log("Vibrate: '%s'\n")
2868 .Always()
2869 .Build());
2870 // clang-format on
2871}
2872
Nandana Dutt979388e2018-11-30 16:48:55 +00002873static void MaybeResolveSymlink(std::string* path) {
2874 std::string resolved_path;
2875 if (android::base::Readlink(*path, &resolved_path)) {
2876 *path = resolved_path;
2877 }
2878}
2879
Nandana Dutt4be45d12018-09-26 15:04:23 +01002880/*
2881 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002882 * and adds the version file. Return false if zip_file could not be open to write.
Nandana Dutt4be45d12018-09-26 15:04:23 +01002883 */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002884static bool PrepareToWriteToFile() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002885 MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2886
Nandana Dutt4be45d12018-09-26 15:04:23 +01002887 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2888 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002889 ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002890 char date[80];
2891 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2892 ds.name_ = date;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002893
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002894 if (ds.options_->telephony_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002895 ds.base_name_ += "-telephony";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002896 } else if (ds.options_->wifi_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002897 ds.base_name_ += "-wifi";
2898 }
2899
Paul Chang0d2aad72020-02-13 20:04:03 +08002900 if (ds.options_->do_screenshot) {
Nandana Dutt9d17b942020-03-26 10:02:59 +00002901 ds.screenshot_path_ = ds.GetPath(ds.CalledByApi() ? "-png.tmp" : ".png");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002902 }
2903 ds.tmp_path_ = ds.GetPath(".tmp");
2904 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2905
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01002906 std::string destination = ds.CalledByApi()
Nandana Dutt54dbd672019-01-11 12:58:05 +00002907 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
Nandana Dutt9a76d202019-01-21 15:56:48 +00002908 : ds.bugreport_internal_dir_.c_str();
Nandana Dutt4be45d12018-09-26 15:04:23 +01002909 MYLOGD(
Nandana Dutt235c6672019-11-14 15:22:32 +00002910 "Bugreport dir: [%s] "
2911 "Base name: [%s] "
2912 "Suffix: [%s] "
2913 "Log path: [%s] "
2914 "Temporary path: [%s] "
2915 "Screenshot path: [%s]\n",
Nandana Dutt9a76d202019-01-21 15:56:48 +00002916 destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2917 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002918
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002919 ds.path_ = ds.GetPath(ds.CalledByApi() ? "-zip.tmp" : ".zip");
2920 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2921 create_parent_dirs(ds.path_.c_str());
2922 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2923 if (ds.zip_file == nullptr) {
2924 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2925 return false;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002926 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002927 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2928 ds.AddTextZipEntry("version.txt", ds.version_);
2929 return true;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002930}
2931
2932/*
Abhijeet Kaure370d682019-10-01 16:49:30 +01002933 * Finalizes writing to the file by zipping the tmp file to the final location,
Nandana Dutt4be45d12018-09-26 15:04:23 +01002934 * printing zipped file status, etc.
2935 */
2936static void FinalizeFile() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002937 bool do_text_file = !ds.FinishZipFile();
2938 if (do_text_file) {
2939 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002940 }
mhasank2d75c442020-06-11 15:05:25 -07002941
2942 std::string final_path = ds.path_;
2943 if (ds.options_->OutputToCustomFile()) {
mhasank3a4cfb42020-06-15 18:06:43 -07002944 final_path = ds.GetPath(ds.options_->out_dir, ".zip");
mhasank2d75c442020-06-11 15:05:25 -07002945 android::os::CopyFileToFile(ds.path_, final_path);
2946 }
2947
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002948 if (ds.options_->stream_to_socket) {
2949 android::os::CopyFileToFd(ds.path_, ds.control_socket_fd_);
2950 } else if (ds.options_->progress_updates_to_socket) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002951 if (do_text_file) {
2952 dprintf(ds.control_socket_fd_,
2953 "FAIL:could not create zip file, check %s "
2954 "for more details\n",
2955 ds.log_path_.c_str());
2956 } else {
mhasank2d75c442020-06-11 15:05:25 -07002957 dprintf(ds.control_socket_fd_, "OK:%s\n", final_path.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002958 }
2959 }
2960}
2961
Nandana Dutt4be45d12018-09-26 15:04:23 +01002962
Nandana Dutt58d72e22018-11-16 10:30:48 +00002963static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2964 switch (mode) {
2965 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2966 return "BUGREPORT_FULL";
2967 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2968 return "BUGREPORT_INTERACTIVE";
2969 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2970 return "BUGREPORT_REMOTE";
2971 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2972 return "BUGREPORT_WEAR";
2973 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2974 return "BUGREPORT_TELEPHONY";
2975 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2976 return "BUGREPORT_WIFI";
Elis Elliott8e401ad2023-08-08 11:18:59 +00002977 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
2978 return "BUGREPORT_ONBOARDING";
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002979 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2980 return "BUGREPORT_DEFAULT";
Nandana Dutt58d72e22018-11-16 10:30:48 +00002981 }
2982}
2983
Steven Leeb573eb82022-11-29 22:31:35 +08002984static bool IsConsentlessBugreportAllowed(const Dumpstate::DumpOptions& options) {
2985 // only BUGREPORT_TELEPHONY does not allow using consentless bugreport
2986 return !options.telephony_only;
2987}
2988
Paul Changf59c2b72020-03-10 02:08:55 +08002989static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options,
2990 bool is_screenshot_requested) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002991 // Modify com.android.shell.BugreportProgressService#isDefaultScreenshotRequired as well for
2992 // default system screenshots.
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002993 options->bugreport_mode = mode;
2994 options->bugreport_mode_string = ModeToString(mode);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002995 switch (mode) {
2996 case Dumpstate::BugreportMode::BUGREPORT_FULL:
Paul Changf59c2b72020-03-10 02:08:55 +08002997 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002998 break;
2999 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003000 // Currently, the dumpstate binder is only used by Shell to update progress.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003001 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08003002 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00003003 break;
3004 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003005 options->do_vibrate = false;
3006 options->is_remote_mode = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08003007 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00003008 break;
3009 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
Robert Ginda55ecebd2023-04-03 22:53:13 +00003010 options->do_vibrate = false;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003011 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08003012 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00003013 break;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08003014 // TODO(b/148168577) rename TELEPHONY everywhere to CONNECTIVITY.
Nandana Dutt58d72e22018-11-16 10:30:48 +00003015 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003016 options->telephony_only = true;
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08003017 options->do_progress_updates = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08003018 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00003019 break;
3020 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003021 options->wifi_only = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08003022 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00003023 break;
Elis Elliott8e401ad2023-08-08 11:18:59 +00003024 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
3025 options->onboarding_only = true;
3026 options->do_screenshot = false;
3027 break;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00003028 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
3029 break;
Nandana Dutt58d72e22018-11-16 10:30:48 +00003030 }
3031}
3032
Nandana Dutt58d72e22018-11-16 10:30:48 +00003033static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
Nandana Dutt235c6672019-11-14 15:22:32 +00003034 MYLOGI(
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003035 "do_vibrate: %d stream_to_socket: %d progress_updates_to_socket: %d do_screenshot: %d "
Rhed Jao25f50e02020-08-20 00:10:32 +08003036 "is_remote_mode: %d show_header_only: %d telephony_only: %d "
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00003037 "wifi_only: %d do_progress_updates: %d fd: %d bugreport_mode: %s "
mhasankd451a472020-05-26 18:02:39 -07003038 "limited_only: %d args: %s\n",
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003039 options.do_vibrate, options.stream_to_socket, options.progress_updates_to_socket,
Paul Chang0d2aad72020-02-13 20:04:03 +08003040 options.do_screenshot, options.is_remote_mode, options.show_header_only,
Rhed Jao25f50e02020-08-20 00:10:32 +08003041 options.telephony_only, options.wifi_only,
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00003042 options.do_progress_updates, options.bugreport_fd.get(),
3043 options.bugreport_mode_string.c_str(),
3044 options.limited_only, options.args.c_str());
Nandana Dutt58d72e22018-11-16 10:30:48 +00003045}
3046
Nandana Dutt54dbd672019-01-11 12:58:05 +00003047void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
Kean Mariotti306633e2022-09-05 16:30:47 +00003048 int bugreport_flags,
Nandana Dutt54dbd672019-01-11 12:58:05 +00003049 const android::base::unique_fd& bugreport_fd_in,
Paul Changf59c2b72020-03-10 02:08:55 +08003050 const android::base::unique_fd& screenshot_fd_in,
Kholoud Mohameddef4e432024-05-15 12:47:46 +00003051 bool is_screenshot_requested,
3052 bool skip_user_consent) {
Kean Mariotti306633e2022-09-05 16:30:47 +00003053 this->use_predumped_ui_data = bugreport_flags & BugreportFlag::BUGREPORT_USE_PREDUMPED_UI_DATA;
Gavin Corkerya44686c2022-11-23 18:16:51 +00003054 this->is_consent_deferred = bugreport_flags & BugreportFlag::BUGREPORT_FLAG_DEFER_CONSENT;
Kholoud Mohameddef4e432024-05-15 12:47:46 +00003055 this->skip_user_consent = skip_user_consent;
Nandana Dutt54dbd672019-01-11 12:58:05 +00003056 // Duplicate the fds because the passed in fds don't outlive the binder transaction.
Todd Frederick621533f2022-03-26 02:54:17 +00003057 bugreport_fd.reset(fcntl(bugreport_fd_in.get(), F_DUPFD_CLOEXEC, 0));
3058 screenshot_fd.reset(fcntl(screenshot_fd_in.get(), F_DUPFD_CLOEXEC, 0));
Nandana Dutt58d72e22018-11-16 10:30:48 +00003059
Paul Changf59c2b72020-03-10 02:08:55 +08003060 SetOptionsFromMode(bugreport_mode, this, is_screenshot_requested);
Nandana Dutt58d72e22018-11-16 10:30:48 +00003061}
3062
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003063Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
3064 RunStatus status = RunStatus::OK;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003065 int c;
mhasankd451a472020-05-26 18:02:39 -07003066 while ((c = getopt(argc, argv, "dho:svqzpLPBRSV:w")) != -1) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003067 switch (c) {
3068 // clang-format off
mhasank3a4cfb42020-06-15 18:06:43 -07003069 case 'o': out_dir = optarg; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003070 case 's': stream_to_socket = true; break;
3071 case 'S': progress_updates_to_socket = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003072 case 'v': show_header_only = true; break;
3073 case 'q': do_vibrate = false; break;
Paul Chang0d2aad72020-02-13 20:04:03 +08003074 case 'p': do_screenshot = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003075 case 'P': do_progress_updates = true; break;
3076 case 'R': is_remote_mode = true; break;
mhasankd451a472020-05-26 18:02:39 -07003077 case 'L': limited_only = true; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003078 case 'V':
3079 case 'd':
3080 case 'z':
3081 // compatibility no-op
3082 break;
Nandana Dutt235864b2019-01-22 12:10:16 +00003083 case 'w':
3084 // This was already processed
3085 break;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003086 case 'h':
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003087 status = RunStatus::HELP;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003088 break;
3089 default:
3090 fprintf(stderr, "Invalid option: %c\n", c);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003091 status = RunStatus::INVALID_INPUT;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003092 break;
3093 // clang-format on
3094 }
3095 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08003096
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003097 for (int i = 0; i < argc; i++) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003098 args += argv[i];
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003099 if (i < argc - 1) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003100 args += " ";
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003101 }
3102 }
3103
3104 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
3105 optind = 1;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003106
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003107 return status;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003108}
3109
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003110bool Dumpstate::DumpOptions::ValidateOptions() const {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003111 if (bugreport_fd.get() != -1 && stream_to_socket) {
Nandana Dutt979388e2018-11-30 16:48:55 +00003112 return false;
3113 }
3114
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003115 if ((progress_updates_to_socket || do_progress_updates) && stream_to_socket) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003116 return false;
3117 }
3118
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003119 if (is_remote_mode && (do_progress_updates || stream_to_socket)) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003120 return false;
3121 }
3122 return true;
3123}
3124
Nandana Dutt197661d2018-11-16 16:40:21 +00003125void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
3126 options_ = std::move(options);
3127}
3128
Abhijeet Kaura407fb82020-03-27 12:51:12 +00003129void Dumpstate::Initialize() {
3130 /* gets the sequential id */
3131 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
3132 id_ = ++last_id;
3133 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
3134}
3135
Nandana Duttd2f5f082019-01-18 17:13:52 +00003136Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
3137 Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
Gavin Corkerya44686c2022-11-23 18:16:51 +00003138 HandleRunStatus(status);
3139 return status;
3140}
3141
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003142Dumpstate::RunStatus Dumpstate::Retrieve(int32_t calling_uid, const std::string& calling_package,
Kholoud Mohameddef4e432024-05-15 12:47:46 +00003143 const bool keep_bugreport_on_retrieval,
3144 const bool skip_user_consent) {
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003145 Dumpstate::RunStatus status = RetrieveInternal(calling_uid, calling_package,
Kholoud Mohameddef4e432024-05-15 12:47:46 +00003146 keep_bugreport_on_retrieval,
3147 skip_user_consent);
Gavin Corkerya44686c2022-11-23 18:16:51 +00003148 HandleRunStatus(status);
3149 return status;
3150}
3151
3152Dumpstate::RunStatus Dumpstate::RetrieveInternal(int32_t calling_uid,
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003153 const std::string& calling_package,
Kholoud Mohameddef4e432024-05-15 12:47:46 +00003154 const bool keep_bugreport_on_retrieval,
3155 const bool skip_user_consent) {
3156 if (!android::app::admin::flags::onboarding_consentless_bugreports() || !skip_user_consent) {
3157 consent_callback_ = new ConsentCallback();
3158 const String16 incidentcompanion("incidentcompanion");
3159 sp<android::IBinder> ics(
3160 defaultServiceManager()->checkService(incidentcompanion));
3161 android::String16 package(calling_package.c_str());
3162 if (ics != nullptr) {
3163 MYLOGD("Checking user consent via incidentcompanion service\n");
3164
3165 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
3166 calling_uid, package, String16(), String16(),
3167 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
3168 } else {
3169 MYLOGD(
3170 "Unable to check user consent; incidentcompanion service unavailable\n");
3171 return RunStatus::USER_CONSENT_TIMED_OUT;
3172 }
3173 UserConsentResult consent_result = consent_callback_->getResult();
3174 int timeout_ms = 30 * 1000;
3175 while (consent_result == UserConsentResult::UNAVAILABLE &&
3176 consent_callback_->getElapsedTimeMs() < timeout_ms) {
3177 sleep(1);
3178 consent_result = consent_callback_->getResult();
3179 }
3180 if (consent_result == UserConsentResult::DENIED) {
3181 return RunStatus::USER_CONSENT_DENIED;
3182 }
3183 if (consent_result == UserConsentResult::UNAVAILABLE) {
3184 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3185 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3186 consent_callback_.get());
3187 return RunStatus::USER_CONSENT_TIMED_OUT;
3188 }
Gavin Corkerya44686c2022-11-23 18:16:51 +00003189 }
3190
3191 bool copy_succeeded =
3192 android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003193
3194 if (copy_succeeded && (!android::app::admin::flags::onboarding_bugreport_v2_enabled()
3195 || !keep_bugreport_on_retrieval)) {
3196 android::os::UnlinkAndLogOnError(path_);
Gavin Corkerya44686c2022-11-23 18:16:51 +00003197 }
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003198
Gavin Corkerya44686c2022-11-23 18:16:51 +00003199 return copy_succeeded ? Dumpstate::RunStatus::OK
3200 : Dumpstate::RunStatus::ERROR;
3201}
3202
3203void Dumpstate::HandleRunStatus(Dumpstate::RunStatus status) {
3204 if (listener_ != nullptr) {
Nandana Duttbabf6c72019-01-15 14:11:12 +00003205 switch (status) {
3206 case Dumpstate::RunStatus::OK:
Gavin Corkerya44686c2022-11-23 18:16:51 +00003207 listener_->onFinished(path_.c_str());
Nandana Duttbabf6c72019-01-15 14:11:12 +00003208 break;
3209 case Dumpstate::RunStatus::HELP:
3210 break;
3211 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003212 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00003213 break;
3214 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003215 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
3216 break;
3217 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3218 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
3219 break;
3220 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
3221 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00003222 break;
3223 }
3224 }
Nandana Duttbabf6c72019-01-15 14:11:12 +00003225}
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003226void Dumpstate::Cancel() {
3227 CleanupTmpFiles();
3228 android::os::UnlinkAndLogOnError(log_path_);
3229 for (int i = 0; i < NUM_OF_DUMPS; i++) {
3230 android::os::UnlinkAndLogOnError(ds.bugreport_internal_dir_ + "/" +
3231 kDumpstateBoardFiles[i]);
3232 }
3233 tombstone_data_.clear();
3234 anr_data_.clear();
Andy Hungd62f7e62024-01-11 15:47:52 -08003235 anr_trace_data_.clear();
Woody Lin20767a92022-11-29 15:50:24 +08003236 shutdown_checkpoints_.clear();
Rhed Jao0daac912020-08-21 14:48:20 +08003237
3238 // Instead of shutdown the pool, we delete temporary files directly since
3239 // shutdown blocking the call.
3240 if (dump_pool_) {
3241 dump_pool_->deleteTempFiles();
3242 }
3243 if (zip_entry_tasks_) {
3244 zip_entry_tasks_->run(/*do_cancel =*/ true);
3245 }
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003246}
3247
Kean Mariotti306633e2022-09-05 16:30:47 +00003248void Dumpstate::PreDumpUiData() {
Kean Mariottica20f2d2023-12-15 09:34:25 +00003249 auto snapshot_system_trace = MaybeSnapshotSystemTraceAsync();
Kean Mariotti306633e2022-09-05 16:30:47 +00003250 MaybeSnapshotUiTraces();
Kean Mariottica20f2d2023-12-15 09:34:25 +00003251 MaybeWaitForSnapshotSystemTrace(std::move(snapshot_system_trace));
Kean Mariotti306633e2022-09-05 16:30:47 +00003252}
3253
Nandana Dutt979388e2018-11-30 16:48:55 +00003254/*
3255 * Dumps relevant information to a bugreport based on the given options.
3256 *
3257 * The bugreport can be dumped to a file or streamed to a socket.
3258 *
3259 * How dumping to file works:
3260 * stdout is redirected to a temporary file. This will later become the main bugreport entry.
3261 * stderr is redirected a log file.
3262 *
3263 * The temporary bugreport is then populated via printfs, dumping contents of files and
3264 * output of commands to stdout.
3265 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003266 * A bunch of other files and dumps are added to the zip archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00003267 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003268 * The temporary bugreport file and the log file also get added to the archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00003269 *
mhasank2d75c442020-06-11 15:05:25 -07003270 * Bugreports are first generated in a local directory and later copied to the caller's fd
3271 * or directory if supplied.
Nandana Dutt979388e2018-11-30 16:48:55 +00003272 */
Nandana Duttd2f5f082019-01-18 17:13:52 +00003273Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
3274 const std::string& calling_package) {
Rhed Jao5377d792020-07-16 17:37:39 +08003275 DurationReporter duration_reporter("RUN INTERNAL", /* logcat_only = */true);
Nandana Dutt979388e2018-11-30 16:48:55 +00003276 LogDumpOptions(*options_);
Nandana Dutt197661d2018-11-16 16:40:21 +00003277 if (!options_->ValidateOptions()) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00003278 MYLOGE("Invalid options specified\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003279 return RunStatus::INVALID_INPUT;
3280 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003281 /* set as high priority, and protect from OOM killer */
3282 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003283
Felipe Lemed071c682016-10-20 16:48:00 -07003284 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07003285 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003286 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003287 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003288 } else {
3289 /* fallback to kernels <= 2.6.35 */
3290 oom_adj = fopen("/proc/self/oom_adj", "we");
3291 if (oom_adj) {
3292 fputs("-17", oom_adj);
3293 fclose(oom_adj);
3294 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003295 }
3296
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003297 if (version_ == VERSION_DEFAULT) {
3298 version_ = VERSION_CURRENT;
Michal Karpinski4db754f2015-12-11 18:04:32 +00003299 }
3300
Chris Morin5a50d482022-02-01 17:41:18 -08003301 if (version_ != VERSION_CURRENT) {
3302 MYLOGE("invalid version requested ('%s'); supported values are: ('%s', '%s')\n",
3303 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003304 return RunStatus::INVALID_INPUT;
Felipe Lemed071c682016-10-20 16:48:00 -07003305 }
3306
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003307 if (options_->show_header_only) {
3308 PrintHeader();
3309 return RunStatus::OK;
Felipe Lemed071c682016-10-20 16:48:00 -07003310 }
3311
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003312 MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n",
3313 calling_uid, calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003314
Felipe Leme7447d7c2016-11-03 18:12:22 -07003315 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003316 std::string stats_path =
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003317 android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003318 progress_.reset(new Progress(stats_path));
Felipe Leme7447d7c2016-11-03 18:12:22 -07003319
Sahana Raof35ed432019-07-12 10:47:52 +01003320 if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
3321 MYLOGE("Failed to acquire wake lock: %s\n", strerror(errno));
3322 } else {
3323 // Wake lock will be released automatically on process death
3324 MYLOGD("Wake lock acquired.\n");
3325 }
3326
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08003327 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07003328
Felipe Lemef0292972016-11-22 13:57:05 -08003329 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07003330 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
3331 }
3332
Kevin Jeonfa64e642023-07-27 11:36:41 -04003333 if (PropertiesHelper::IsStrictRun()) {
3334 MYLOGI(
3335 "Running on strict-run mode, which has shorter timeouts "
3336 "(to disable, call 'setprop dumpstate.strict_run false')\n");
3337 }
3338
Nandana Dutt235c6672019-11-14 15:22:32 +00003339 MYLOGI("dumpstate info: id=%d, args='%s', bugreport_mode= %s bugreport format version: %s\n",
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00003340 id_, options_->args.c_str(), options_->bugreport_mode_string.c_str(), version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08003341
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003342 do_early_screenshot_ = options_->do_progress_updates;
Felipe Lemee338bf62015-12-07 14:03:50 -08003343
Christopher Ferrised9354f2014-10-01 17:35:01 -07003344 // If we are going to use a socket, do it as early as possible
3345 // to avoid timeouts from bugreport.
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003346 if (options_->stream_to_socket || options_->progress_updates_to_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07003347 MYLOGD("Opening control socket\n");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003348 control_socket_fd_ = open_socket_fn_("dumpstate");
Nandana Dutta344cb62019-02-22 15:12:35 +00003349 if (control_socket_fd_ == -1) {
3350 return ERROR;
3351 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003352 if (options_->progress_updates_to_socket) {
3353 options_->do_progress_updates = 1;
3354 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07003355 }
3356
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003357 if (!PrepareToWriteToFile()) {
3358 return ERROR;
3359 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08003360
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003361 // Interactive, wear & telephony modes are default to true.
3362 // and may enable from cli option or when using control socket
3363 if (options_->do_progress_updates) {
3364 // clang-format off
3365 std::vector<std::string> am_args = {
3366 "--receiver-permission", "android.permission.DUMP",
3367 };
3368 // clang-format on
3369 // Send STARTED broadcast for apps that listen to bugreport generation events
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003370 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED",
3371 am_args, multiuser_get_user_id(calling_uid));
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003372 if (options_->progress_updates_to_socket) {
3373 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08003374 }
3375 }
3376
Nick Kralevichf3599b32016-01-25 15:05:16 -08003377 /* read /proc/cmdline before dropping root */
3378 FILE *cmdline = fopen("/proc/cmdline", "re");
3379 if (cmdline) {
3380 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
3381 fclose(cmdline);
3382 }
3383
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003384 if (options_->do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08003385 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05003386 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003387
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003388 if (zip_file != nullptr) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003389 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
3390 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003391 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08003392 }
3393 }
3394
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003395 int dup_stdout_fd;
3396 int dup_stderr_fd;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003397 // Redirect stderr to log_path_ for debugging.
3398 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
3399 if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
3400 return ERROR;
3401 }
3402 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
3403 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
3404 strerror(errno));
3405 }
Nandana Dutt979388e2018-11-30 16:48:55 +00003406
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003407 // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
3408 // moved into zip file later, if zipping.
3409 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
3410 // TODO: why not write to a file instead of stdout to overcome this problem?
3411 /* TODO: rather than generating a text file now and zipping it later,
3412 it would be more efficient to redirect stdout to the zip entry
3413 directly, but the libziparchive doesn't support that option yet. */
3414 if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
3415 return ERROR;
3416 }
3417 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
3418 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
3419 tmp_path_.c_str(), strerror(errno));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003420 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08003421
3422 // Don't buffer stdout
3423 setvbuf(stdout, nullptr, _IONBF, 0);
3424
Rhed Jao5377d792020-07-16 17:37:39 +08003425 // Enable the parallel run if the client requests to output to a file.
3426 EnableParallelRunIfNeeded();
3427 // Using scope guard to make sure the dump pool can be shut down correctly.
3428 auto scope_guard_to_shutdown_pool = android::base::make_scope_guard([=]() {
3429 ShutdownDumpPool();
3430 });
3431
Felipe Leme608385d2016-02-01 10:35:38 -08003432 // NOTE: there should be no stdout output until now, otherwise it would break the header.
3433 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08003434 // duration is logged into MYLOG instead.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003435 PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003436
Primiano Tucci06d34202025-02-13 11:17:06 -08003437 size_t trace_count = android::os::ForEachTrace([](const std::string&) {});
3438 if (options_->use_predumped_ui_data && trace_count == 0) {
Kean Mariottic14cebc2024-03-04 10:55:28 +00003439 MYLOGW("Ignoring 'use predumped data' flag because no predumped data is available");
3440 options_->use_predumped_ui_data = false;
3441 }
3442
Kean Mariottica20f2d2023-12-15 09:34:25 +00003443 std::future<std::string> snapshot_system_trace;
3444
Kean Mariotti853b73a2023-07-27 12:40:30 +00003445 bool is_dumpstate_restricted =
3446 options_->telephony_only || options_->wifi_only || options_->limited_only;
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003447 if (!is_dumpstate_restricted) {
3448 // Snapshot the system trace now (if running) to avoid that dumpstate's
3449 // own activity pushes out interesting data from the trace ring buffer.
3450 // The trace file is added to the zip by MaybeAddSystemTraceToZip().
Kean Mariottica20f2d2023-12-15 09:34:25 +00003451 snapshot_system_trace = MaybeSnapshotSystemTraceAsync();
Yohei Yukawa95305b32021-03-09 07:54:27 -08003452
Kean Mariotti853b73a2023-07-27 12:40:30 +00003453 // Invoke critical dumpsys to preserve system state, before doing anything else.
3454 RunDumpsysCritical();
3455
Kean Mariotti306633e2022-09-05 16:30:47 +00003456 // Snapshot the UI traces now (if running).
3457 // The trace files will be added to bugreport later.
3458 MaybeSnapshotUiTraces();
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003459 }
Kean Mariotti853b73a2023-07-27 12:40:30 +00003460
3461 MaybeTakeEarlyScreenshot();
Kean Mariottica20f2d2023-12-15 09:34:25 +00003462 MaybeWaitForSnapshotSystemTrace(std::move(snapshot_system_trace));
Gavin Corkery6968f552020-11-22 18:09:05 +00003463 onUiIntensiveBugreportDumpsFinished(calling_uid);
3464 MaybeCheckUserConsent(calling_uid, calling_package);
3465 if (options_->telephony_only) {
3466 DumpstateTelephonyOnly(calling_package);
3467 } else if (options_->wifi_only) {
3468 DumpstateWifiOnly();
3469 } else if (options_->limited_only) {
3470 DumpstateLimitedOnly();
Elis Elliott8e401ad2023-08-08 11:18:59 +00003471 } else if (options_->onboarding_only) {
3472 DumpstateOnboardingOnly();
Gavin Corkery6968f552020-11-22 18:09:05 +00003473 } else {
Nandana Dutt4be45d12018-09-26 15:04:23 +01003474 // Dump state for the default case. This also drops root.
Jichao Lie89d9c12019-11-21 19:02:51 -08003475 RunStatus s = DumpstateDefaultAfterCritical();
Nandana Dutt5c390032019-03-12 10:52:56 +00003476 if (s != RunStatus::OK) {
Nandana Duttaac6f582019-07-26 14:32:47 +01003477 if (s == RunStatus::USER_CONSENT_DENIED) {
Nandana Dutt5c390032019-03-12 10:52:56 +00003478 HandleUserConsentDenied();
3479 }
3480 return s;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08003481 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07003482 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07003483
Felipe Leme55b42a62015-11-10 17:39:08 -08003484 /* close output if needed */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003485 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003486
Abhijeet Kaure370d682019-10-01 16:49:30 +01003487 // Zip the (now complete) .tmp file within the internal directory.
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003488 ATRACE_BEGIN("FinalizeFile");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003489 FinalizeFile();
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003490 ATRACE_END();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003491
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003492 // Share the final file with the caller if the user has consented or Shell is the caller.
Nandana Duttd2f5f082019-01-18 17:13:52 +00003493 Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
Gavin Corkerya44686c2022-11-23 18:16:51 +00003494 if (CalledByApi() && !options_->is_consent_deferred) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003495 status = CopyBugreportIfUserConsented(calling_uid);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003496 if (status != Dumpstate::RunStatus::OK &&
3497 status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3498 // Do an early return if there were errors. We make an exception for consent
3499 // timing out because it's possible the user got distracted. In this case the
3500 // bugreport is not shared but made available for manual retrieval.
Kunduz Baryktabasova3a5b65a2024-10-07 11:53:48 +00003501 MYLOGI("Bug report generation failed, this could have been due to"
3502 " several reasons such as BR copy failed, user consent was"
3503 " not grated etc. Returning\n");
Nandana Duttd2f5f082019-01-18 17:13:52 +00003504 return status;
3505 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003506 if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3507 MYLOGI(
3508 "Did not receive user consent yet."
3509 " Will not copy the bugreport artifacts to caller.\n");
Abhijeet Kaur57627412019-04-17 16:00:09 +01003510 const String16 incidentcompanion("incidentcompanion");
3511 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
3512 if (ics != nullptr) {
3513 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3514 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3515 consent_callback_.get());
3516 } else {
3517 MYLOGD("Unable to cancel user consent; incidentcompanion service unavailable\n");
3518 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003519 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003520 }
3521
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003522 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003523 if (options_->do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09003524 for (int i = 0; i < 3; i++) {
3525 Vibrate(75);
3526 usleep((75 + 50) * 1000);
3527 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003528 }
3529
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003530 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
3531 progress_->GetInitialMax());
3532 progress_->Save();
3533 MYLOGI("done (id %d)\n", id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003534
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003535 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08003536
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003537 if (control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07003538 MYLOGD("Closing control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003539 close(control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07003540 }
3541
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003542 tombstone_data_.clear();
3543 anr_data_.clear();
Andy Hungd62f7e62024-01-11 15:47:52 -08003544 anr_trace_data_.clear();
Woody Lin20767a92022-11-29 15:50:24 +08003545 shutdown_checkpoints_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01003546
Nandana Duttd2f5f082019-01-18 17:13:52 +00003547 return (consent_callback_ != nullptr &&
3548 consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
3549 ? USER_CONSENT_TIMED_OUT
3550 : RunStatus::OK;
3551}
3552
Paul Chang0d2aad72020-02-13 20:04:03 +08003553void Dumpstate::MaybeTakeEarlyScreenshot() {
3554 if (!options_->do_screenshot || !do_early_screenshot_) {
3555 return;
3556 }
3557
3558 TakeScreenshot();
3559}
3560
Kean Mariottica20f2d2023-12-15 09:34:25 +00003561std::future<std::string> Dumpstate::MaybeSnapshotSystemTraceAsync() {
Kean Mariotti853b73a2023-07-27 12:40:30 +00003562 // When capturing traces via bugreport handler (BH), this function will be invoked twice:
3563 // 1) When BH invokes IDumpstate::PreDumpUiData()
3564 // 2) When BH invokes IDumpstate::startBugreport(flags = BUGREPORT_USE_PREDUMPED_UI_DATA)
3565 // In this case we don't want to re-invoke perfetto in step 2.
3566 // In all other standard invocation states, this function is invoked once
3567 // without the flag BUGREPORT_USE_PREDUMPED_UI_DATA.
Kean Mariottica20f2d2023-12-15 09:34:25 +00003568 // This function must run asynchronously to avoid delaying MaybeTakeEarlyScreenshot() in the
3569 // standard invocation states (b/316110955).
Kean Mariotti853b73a2023-07-27 12:40:30 +00003570 if (options_->use_predumped_ui_data) {
Kean Mariottica20f2d2023-12-15 09:34:25 +00003571 return {};
3572 }
3573
3574 // Create temporary file for the command's output
3575 std::string outPath = ds.bugreport_internal_dir_ + "/tmp_serialize_perfetto_trace";
3576 auto outFd = android::base::unique_fd(TEMP_FAILURE_RETRY(
3577 open(outPath.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
3578 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
3579 if (outFd < 0) {
3580 MYLOGE("Could not open %s to serialize perfetto trace.\n", outPath.c_str());
3581 return {};
Kean Mariotti853b73a2023-07-27 12:40:30 +00003582 }
3583
3584 // If a stale file exists already, remove it.
Primiano Tucci06d34202025-02-13 11:17:06 -08003585 android::os::ForEachTrace([&](const std::string& trace_path) { unlink(trace_path.c_str()); });
Kean Mariotti853b73a2023-07-27 12:40:30 +00003586
Kean Mariottica20f2d2023-12-15 09:34:25 +00003587 MYLOGI("Launching async '%s'", SERIALIZE_PERFETTO_TRACE_TASK.c_str())
Primiano Tucci06d34202025-02-13 11:17:06 -08003588
Kean Mariottica20f2d2023-12-15 09:34:25 +00003589 return std::async(
3590 std::launch::async, [this, outPath = std::move(outPath), outFd = std::move(outFd)] {
Primiano Tucci06d34202025-02-13 11:17:06 -08003591 // If one or more background system traces are happening and are marked as
3592 // "suitable for bugreport" (bugreport_score > 0 in the trace config), this command
3593 // will snapshot them into SYSTEM_TRACE_DIR.
3594 // In the (likely) case that no trace is ongoing, this command is a no-op.
Kean Mariottica20f2d2023-12-15 09:34:25 +00003595 // Note: this should not be enqueued as we need to freeze the trace before
3596 // dumpstate starts. Otherwise the trace ring buffers will contain mostly
3597 // the dumpstate's own activity which is irrelevant.
Primiano Tucci06d34202025-02-13 11:17:06 -08003598 const char* cmd_arg = perfetto::flags::save_all_traces_in_bugreport()
3599 ? "--save-all-for-bugreport"
3600 : "--save-for-bugreport";
Kean Mariottica20f2d2023-12-15 09:34:25 +00003601 RunCommand(
Primiano Tucci06d34202025-02-13 11:17:06 -08003602 SERIALIZE_PERFETTO_TRACE_TASK, {"perfetto", cmd_arg},
Kean Mariotti5aa8d152024-09-23 12:10:09 +00003603 CommandOptions::WithTimeout(30).DropRoot().CloseAllFileDescriptorsOnExec().Build(),
Kean Mariottica20f2d2023-12-15 09:34:25 +00003604 false, outFd);
3605 // MaybeAddSystemTraceToZip() will take care of copying the trace in the zip
3606 // file in the later stages.
3607
3608 return outPath;
3609 });
3610}
3611
3612void Dumpstate::MaybeWaitForSnapshotSystemTrace(std::future<std::string> task) {
3613 if (!task.valid()) {
3614 return;
3615 }
3616
3617 WaitForTask(std::move(task), SERIALIZE_PERFETTO_TRACE_TASK, STDOUT_FILENO);
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003618}
3619
Kean Mariotti306633e2022-09-05 16:30:47 +00003620void Dumpstate::MaybeSnapshotUiTraces() {
3621 if (PropertiesHelper::IsUserBuild() || options_->use_predumped_ui_data) {
3622 return;
3623 }
3624
Pablo Gamito654831c2024-02-16 16:47:48 +00003625 std::vector<std::vector<std::string>> dumpTracesForBugReportCommands = {
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003626 {"cmd", "input_method", "tracing", "save-for-bugreport"},
3627 {"cmd", "window", "tracing", "save-for-bugreport"},
3628 {"cmd", "window", "shell", "tracing", "save-for-bugreport"},
3629 };
Hongwei Wang39229132023-01-24 15:09:59 -08003630
Pablo Gamito654831c2024-02-16 16:47:48 +00003631 if (!android_tracing_perfetto_transition_tracing()) {
3632 dumpTracesForBugReportCommands.push_back({"dumpsys", "activity", "service",
3633 "SystemUIService", "WMShell", "transitions",
3634 "tracing", "save-for-bugreport"});
3635 }
3636
Pablo Gamito6929a0e2024-02-26 23:29:47 +00003637 if (!android_tracing_perfetto_protolog_tracing()) {
Pablo Gamito654831c2024-02-16 16:47:48 +00003638 dumpTracesForBugReportCommands.push_back({"dumpsys", "activity", "service",
3639 "SystemUIService", "WMShell", "protolog",
3640 "save-for-bugreport"});
3641 }
3642
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003643 for (const auto& command : dumpTracesForBugReportCommands) {
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003644 RunCommand(
3645 // Empty name because it's not intended to be classified as a bugreport section.
3646 // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003647 "", command,
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003648 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
3649 }
Kean Mariotti306633e2022-09-05 16:30:47 +00003650}
3651
3652void Dumpstate::MaybeAddUiTracesToZip() {
3653 if (PropertiesHelper::IsUserBuild()) {
3654 return;
3655 }
3656
3657 ds.AddDir(WMTRACE_DATA_DIR, false);
Yohei Yukawa95305b32021-03-09 07:54:27 -08003658}
3659
Paul Changeb4b4642020-05-28 22:05:47 +08003660void Dumpstate::onUiIntensiveBugreportDumpsFinished(int32_t calling_uid) {
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003661 if (multiuser_get_app_id(calling_uid) == AID_SHELL || !CalledByApi()) {
Paul Changc490e662020-04-11 18:14:09 +08003662 return;
3663 }
3664 if (listener_ != nullptr) {
3665 // Let listener know ui intensive bugreport dumps are finished, then it can do event
3666 // handling if required.
Paul Changeb4b4642020-05-28 22:05:47 +08003667 listener_->onUiIntensiveBugreportDumpsFinished();
Paul Changc490e662020-04-11 18:14:09 +08003668 }
3669}
3670
Jichao Lie89d9c12019-11-21 19:02:51 -08003671void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) {
Gavin Corkerya44686c2022-11-23 18:16:51 +00003672 if (multiuser_get_app_id(calling_uid) == AID_SHELL ||
Kholoud Mohameddef4e432024-05-15 12:47:46 +00003673 !CalledByApi() || options_->is_consent_deferred ||
3674 (android::app::admin::flags::onboarding_consentless_bugreports() &&
3675 options_->skip_user_consent)) {
Gavin Corkerya44686c2022-11-23 18:16:51 +00003676 // No need to get consent for shell triggered dumpstates, or not
3677 // through bugreporting API (i.e. no fd to copy back), or when consent
3678 // is deferred.
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003679 return;
3680 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003681 consent_callback_ = new ConsentCallback();
3682 const String16 incidentcompanion("incidentcompanion");
3683 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
Jichao Lie89d9c12019-11-21 19:02:51 -08003684 android::String16 package(calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003685 if (ics != nullptr) {
3686 MYLOGD("Checking user consent via incidentcompanion service\n");
Steven Leeb573eb82022-11-29 22:31:35 +08003687 int flags = 0x1; // IncidentManager.FLAG_CONFIRMATION_DIALOG
3688 if (IsConsentlessBugreportAllowed(*options_)) {
3689 flags |= 0x2; // IncidentManager.FLAG_ALLOW_CONSENTLESS_BUGREPORT
3690 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003691 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
Steven Leeb573eb82022-11-29 22:31:35 +08003692 calling_uid, package, String16(), String16(), flags, consent_callback_.get());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003693 } else {
3694 MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
3695 }
3696}
3697
Nandana Dutt5c390032019-03-12 10:52:56 +00003698bool Dumpstate::IsUserConsentDenied() const {
3699 return ds.consent_callback_ != nullptr &&
3700 ds.consent_callback_->getResult() == UserConsentResult::DENIED;
3701}
3702
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01003703bool Dumpstate::CalledByApi() const {
3704 return ds.options_->bugreport_fd.get() != -1 ? true : false;
3705}
3706
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003707void Dumpstate::CleanupTmpFiles() {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003708 android::os::UnlinkAndLogOnError(tmp_path_);
3709 android::os::UnlinkAndLogOnError(screenshot_path_);
3710 android::os::UnlinkAndLogOnError(path_);
Gavin Corkery789d7a52021-02-24 23:52:35 +00003711 if (dump_traces_path != nullptr) {
3712 android::os::UnlinkAndLogOnError(dump_traces_path);
3713 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003714}
3715
Rhed Jao5377d792020-07-16 17:37:39 +08003716void Dumpstate::EnableParallelRunIfNeeded() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003717 if (!PropertiesHelper::IsParallelRun()) {
Rhed Jao5377d792020-07-16 17:37:39 +08003718 return;
3719 }
3720 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003721 zip_entry_tasks_ = std::make_unique<TaskQueue>();
Rhed Jao5377d792020-07-16 17:37:39 +08003722}
3723
3724void Dumpstate::ShutdownDumpPool() {
3725 if (dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08003726 dump_pool_.reset();
Rhed Jao5377d792020-07-16 17:37:39 +08003727 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003728 if (zip_entry_tasks_) {
3729 zip_entry_tasks_->run(/* do_cancel = */true);
3730 zip_entry_tasks_ = nullptr;
3731 }
3732}
3733
3734void Dumpstate::EnqueueAddZipEntryAndCleanupIfNeeded(const std::string& entry_name,
3735 const std::string& entry_path) {
3736 auto func_add_zip_entry_and_cleanup = [=](bool task_cancelled) {
3737 if (!task_cancelled) {
3738 AddZipEntry(entry_name, entry_path);
3739 }
3740 android::os::UnlinkAndLogOnError(entry_path);
3741 };
3742 if (zip_entry_tasks_) {
3743 // Enqueues AddZipEntryAndCleanup function if the parallel run is enabled.
3744 zip_entry_tasks_->add(func_add_zip_entry_and_cleanup, _1);
3745 } else {
3746 // Invokes AddZipEntryAndCleanup immediately
3747 std::invoke(func_add_zip_entry_and_cleanup, /* task_cancelled = */false);
3748 }
Rhed Jao5377d792020-07-16 17:37:39 +08003749}
3750
Nandana Duttd2f5f082019-01-18 17:13:52 +00003751Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
3752 MYLOGD("User denied consent; deleting files and returning\n");
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003753 CleanupTmpFiles();
Nandana Duttd2f5f082019-01-18 17:13:52 +00003754 return USER_CONSENT_DENIED;
3755}
3756
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003757Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented(int32_t calling_uid) {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003758 // If the caller has asked to copy the bugreport over to their directory, we need explicit
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003759 // user consent (unless the caller is Shell).
3760 UserConsentResult consent_result;
Kholoud Mohameddef4e432024-05-15 12:47:46 +00003761 if (multiuser_get_app_id(calling_uid) == AID_SHELL || (options_->skip_user_consent
3762 && android::app::admin::flags::onboarding_consentless_bugreports())) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003763 consent_result = UserConsentResult::APPROVED;
3764 } else {
3765 consent_result = consent_callback_->getResult();
3766 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003767 if (consent_result == UserConsentResult::UNAVAILABLE) {
3768 // User has not responded yet.
3769 uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
Hunter Knepshield70610fa2020-01-03 15:27:33 -08003770 // Telephony is a fast report type, particularly on user builds where information may be
3771 // more aggressively limited. To give the user time to read the consent dialog, increase the
3772 // timeout.
3773 uint64_t timeout_ms = options_->telephony_only ? TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS
3774 : USER_CONSENT_TIMEOUT_MS;
3775 if (elapsed_ms < timeout_ms) {
3776 uint delay_seconds = (timeout_ms - elapsed_ms) / 1000;
Nandana Duttd2f5f082019-01-18 17:13:52 +00003777 MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
3778 sleep(delay_seconds);
3779 }
3780 consent_result = consent_callback_->getResult();
3781 }
3782 if (consent_result == UserConsentResult::DENIED) {
3783 // User has explicitly denied sharing with the app. To be safe delete the
3784 // internal bugreport & tmp files.
3785 return HandleUserConsentDenied();
3786 }
3787 if (consent_result == UserConsentResult::APPROVED) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00003788 bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
3789 if (copy_succeeded) {
3790 android::os::UnlinkAndLogOnError(path_);
Abhijeet Kaur9ce94672020-04-01 17:22:36 +01003791 if (options_->do_screenshot &&
3792 options_->screenshot_fd.get() != -1 &&
3793 !options_->is_screenshot_copied) {
Kunduz Baryktabasova3a5b65a2024-10-07 11:53:48 +00003794 bool is_screenshot_copied = android::os::CopyFileToFd(screenshot_path_,
Abhijeet Kaur9ce94672020-04-01 17:22:36 +01003795 options_->screenshot_fd.get());
Kunduz Baryktabasova3a5b65a2024-10-07 11:53:48 +00003796 if (is_screenshot_copied) {
Abhijeet Kaur9ce94672020-04-01 17:22:36 +01003797 android::os::UnlinkAndLogOnError(screenshot_path_);
Kunduz Baryktabasova3a5b65a2024-10-07 11:53:48 +00003798 } else {
3799 MYLOGE("Failed to copy screenshot to a permanent file.\n");
3800 is_screenshot_copied = android::os::CopyFileToFd(DEFAULT_SCREENSHOT_PATH,
3801 options_->screenshot_fd.get());
Abhijeet Kaur9ce94672020-04-01 17:22:36 +01003802 }
Kunduz Baryktabasova3a5b65a2024-10-07 11:53:48 +00003803 options_->is_screenshot_copied = is_screenshot_copied;
Abhijeet Kaur9ce94672020-04-01 17:22:36 +01003804 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003805 }
3806 return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
3807 } else if (consent_result == UserConsentResult::UNAVAILABLE) {
3808 // consent_result is still UNAVAILABLE. The user has likely not responded yet.
3809 // Since we do not have user consent to share the bugreport it does not get
3810 // copied over to the calling app but remains in the internal directory from
3811 // where the user can manually pull it.
Paul Changce644212021-05-11 16:06:45 +08003812 std::string final_path = GetPath(".zip");
3813 bool copy_succeeded = android::os::CopyFileToFile(path_, final_path);
3814 if (copy_succeeded) {
3815 android::os::UnlinkAndLogOnError(path_);
3816 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003817 return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
3818 }
3819 // Unknown result; must be a programming error.
3820 MYLOGE("Unknown user consent result:%d\n", consent_result);
3821 return Dumpstate::RunStatus::ERROR;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003822}
3823
Nandana Duttf02564e2019-02-15 15:24:24 +00003824Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003825 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
3826 Dumpstate::RunStatus status = options->Initialize(argc, argv);
3827 if (status == Dumpstate::RunStatus::OK) {
Nandana Duttf02564e2019-02-15 15:24:24 +00003828 SetOptions(std::move(options));
Nandana Duttd2f5f082019-01-18 17:13:52 +00003829 // When directly running dumpstate binary, the output is not expected to be written
3830 // to any external file descriptor.
Nandana Duttf02564e2019-02-15 15:24:24 +00003831 assert(options_->bugreport_fd.get() == -1);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003832
3833 // calling_uid and calling_package are for user consent to share the bugreport with
Abhijeet Kaura407fb82020-03-27 12:51:12 +00003834 // an app; they are irrelevant here because bugreport is triggered via command line.
3835 // Update Last ID before calling Run().
3836 Initialize();
Nikhil Kumarb70622a2023-06-15 15:37:19 +01003837 status = Run(0 /* calling_uid */, "" /* calling_package */);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003838 }
Nandana Duttf02564e2019-02-15 15:24:24 +00003839 return status;
3840}
3841
3842/* Main entry point for dumpstate binary. */
3843int run_main(int argc, char* argv[]) {
3844 Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003845
3846 switch (status) {
3847 case Dumpstate::RunStatus::OK:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003848 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003849 case Dumpstate::RunStatus::HELP:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003850 ShowUsage();
3851 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003852 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003853 fprintf(stderr, "Invalid combination of args\n");
3854 ShowUsage();
3855 exit(1);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003856 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003857 FALLTHROUGH_INTENDED;
3858 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3859 FALLTHROUGH_INTENDED;
3860 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003861 exit(2);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003862 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003863}
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003864
3865// TODO(111441001): Default DumpOptions to sensible values.
3866Dumpstate::Dumpstate(const std::string& version)
3867 : pid_(getpid()),
3868 options_(new Dumpstate::DumpOptions()),
Nandana Dutt402a8392019-06-14 14:25:13 +01003869 last_reported_percent_progress_(0),
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003870 version_(version),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003871 now_(time(nullptr)),
3872 open_socket_fn_(open_socket) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003873}
3874
3875Dumpstate& Dumpstate::GetInstance() {
3876 static Dumpstate singleton_(android::base::GetProperty("dumpstate.version", VERSION_CURRENT));
3877 return singleton_;
3878}
3879
Rhed Jao5377d792020-07-16 17:37:39 +08003880DurationReporter::DurationReporter(const std::string& title, bool logcat_only, bool verbose,
3881 int duration_fd) : title_(title), logcat_only_(logcat_only), verbose_(verbose),
3882 duration_fd_(duration_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003883 if (!title_.empty()) {
3884 started_ = Nanotime();
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003885 if (title_.find("SHOW MAP") == std::string::npos) {
3886 ATRACE_ASYNC_BEGIN(title_.c_str(), 0);
3887 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003888 }
3889}
3890
3891DurationReporter::~DurationReporter() {
3892 if (!title_.empty()) {
3893 float elapsed = (float)(Nanotime() - started_) / NANOS_PER_SEC;
Kunduz Baryktabasova3a5b65a2024-10-07 11:53:48 +00003894 if (elapsed >= 1.0f || verbose_) {
chenqiwuaf8b2d92019-12-12 18:53:51 +08003895 MYLOGD("Duration of '%s': %.2fs\n", title_.c_str(), elapsed);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003896 }
chenqiwuaf8b2d92019-12-12 18:53:51 +08003897 if (!logcat_only_) {
3898 // Use "Yoda grammar" to make it easier to grep|sort sections.
Rhed Jao5377d792020-07-16 17:37:39 +08003899 dprintf(duration_fd_, "------ %.3fs was the duration of '%s' ------\n",
3900 elapsed, title_.c_str());
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003901 }
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003902 if (title_.find("SHOW MAP") == std::string::npos) {
3903 ATRACE_ASYNC_END(title_.c_str(), 0);
3904 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003905 }
3906}
3907
3908const int32_t Progress::kDefaultMax = 5000;
3909
3910Progress::Progress(const std::string& path) : Progress(Progress::kDefaultMax, 1.1, path) {
3911}
3912
3913Progress::Progress(int32_t initial_max, int32_t progress, float growth_factor)
3914 : Progress(initial_max, growth_factor, "") {
3915 progress_ = progress;
3916}
3917
3918Progress::Progress(int32_t initial_max, float growth_factor, const std::string& path)
3919 : initial_max_(initial_max),
3920 progress_(0),
3921 max_(initial_max),
3922 growth_factor_(growth_factor),
3923 n_runs_(0),
3924 average_max_(0),
3925 path_(path) {
3926 if (!path_.empty()) {
3927 Load();
3928 }
3929}
3930
3931void Progress::Load() {
3932 MYLOGD("Loading stats from %s\n", path_.c_str());
3933 std::string content;
3934 if (!android::base::ReadFileToString(path_, &content)) {
3935 MYLOGI("Could not read stats from %s; using max of %d\n", path_.c_str(), max_);
3936 return;
3937 }
3938 if (content.empty()) {
3939 MYLOGE("No stats (empty file) on %s; using max of %d\n", path_.c_str(), max_);
3940 return;
3941 }
3942 std::vector<std::string> lines = android::base::Split(content, "\n");
3943
3944 if (lines.size() < 1) {
3945 MYLOGE("Invalid stats on file %s: not enough lines (%d). Using max of %d\n", path_.c_str(),
3946 (int)lines.size(), max_);
3947 return;
3948 }
3949 char* ptr;
3950 n_runs_ = strtol(lines[0].c_str(), &ptr, 10);
3951 average_max_ = strtol(ptr, nullptr, 10);
3952 if (n_runs_ <= 0 || average_max_ <= 0 || n_runs_ > STATS_MAX_N_RUNS ||
3953 average_max_ > STATS_MAX_AVERAGE) {
3954 MYLOGE("Invalid stats line on file %s: %s\n", path_.c_str(), lines[0].c_str());
3955 initial_max_ = Progress::kDefaultMax;
3956 } else {
3957 initial_max_ = average_max_;
3958 }
3959 max_ = initial_max_;
3960
3961 MYLOGI("Average max progress: %d in %d runs; estimated max: %d\n", average_max_, n_runs_, max_);
3962}
3963
3964void Progress::Save() {
3965 int32_t total = n_runs_ * average_max_ + progress_;
3966 int32_t runs = n_runs_ + 1;
3967 int32_t average = floor(((float)total) / runs);
3968 MYLOGI("Saving stats (total=%d, runs=%d, average=%d) on %s\n", total, runs, average,
3969 path_.c_str());
3970 if (path_.empty()) {
3971 return;
3972 }
3973
3974 std::string content = android::base::StringPrintf("%d %d\n", runs, average);
3975 if (!android::base::WriteStringToFile(content, path_)) {
3976 MYLOGE("Could not save stats on %s\n", path_.c_str());
3977 }
3978}
3979
3980int32_t Progress::Get() const {
3981 return progress_;
3982}
3983
3984bool Progress::Inc(int32_t delta_sec) {
3985 bool changed = false;
3986 if (delta_sec >= 0) {
3987 progress_ += delta_sec;
3988 if (progress_ > max_) {
3989 int32_t old_max = max_;
3990 max_ = floor((float)progress_ * growth_factor_);
3991 MYLOGD("Adjusting max progress from %d to %d\n", old_max, max_);
3992 changed = true;
3993 }
3994 }
3995 return changed;
3996}
3997
3998int32_t Progress::GetMax() const {
3999 return max_;
4000}
4001
4002int32_t Progress::GetInitialMax() const {
4003 return initial_max_;
4004}
4005
4006void Progress::Dump(int fd, const std::string& prefix) const {
4007 const char* pr = prefix.c_str();
4008 dprintf(fd, "%sprogress: %d\n", pr, progress_);
4009 dprintf(fd, "%smax: %d\n", pr, max_);
4010 dprintf(fd, "%sinitial_max: %d\n", pr, initial_max_);
4011 dprintf(fd, "%sgrowth_factor: %0.2f\n", pr, growth_factor_);
4012 dprintf(fd, "%spath: %s\n", pr, path_.c_str());
4013 dprintf(fd, "%sn_runs: %d\n", pr, n_runs_);
4014 dprintf(fd, "%saverage_max: %d\n", pr, average_max_);
4015}
4016
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004017std::string Dumpstate::GetPath(const std::string& suffix) const {
4018 return GetPath(bugreport_internal_dir_, suffix);
4019}
4020
4021std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
4022 return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
4023 name_.c_str(), suffix.c_str());
4024}
4025
4026void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
4027 progress_ = std::move(progress);
4028}
4029
4030void for_each_userid(void (*func)(int), const char *header) {
4031 std::string title = header == nullptr ? "for_each_userid" : android::base::StringPrintf(
4032 "for_each_userid(%s)", header);
4033 DurationReporter duration_reporter(title);
4034 if (PropertiesHelper::IsDryRun()) return;
4035
4036 DIR *d;
4037 struct dirent *de;
4038
4039 if (header) printf("\n------ %s ------\n", header);
4040 func(0);
4041
4042 if (!(d = opendir("/data/system/users"))) {
4043 printf("Failed to open /data/system/users (%s)\n", strerror(errno));
4044 return;
4045 }
4046
4047 while ((de = readdir(d))) {
4048 int userid;
4049 if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
4050 continue;
4051 }
4052 func(userid);
4053 }
4054
4055 closedir(d);
4056}
4057
4058static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
4059 DIR *d;
4060 struct dirent *de;
4061
4062 if (!(d = opendir("/proc"))) {
4063 printf("Failed to open /proc (%s)\n", strerror(errno));
4064 return;
4065 }
4066
4067 if (header) printf("\n------ %s ------\n", header);
4068 while ((de = readdir(d))) {
4069 if (ds.IsUserConsentDenied()) {
4070 MYLOGE(
4071 "Returning early because user denied consent to share bugreport with calling app.");
4072 closedir(d);
4073 return;
4074 }
4075 int pid;
4076 int fd;
4077 char cmdpath[255];
4078 char cmdline[255];
4079
4080 if (!(pid = atoi(de->d_name))) {
4081 continue;
4082 }
4083
4084 memset(cmdline, 0, sizeof(cmdline));
4085
4086 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
4087 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
4088 TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
4089 close(fd);
4090 if (cmdline[0]) {
4091 helper(pid, cmdline, arg);
4092 continue;
4093 }
4094 }
4095
4096 // if no cmdline, a kernel thread has comm
4097 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
4098 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
4099 TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
4100 close(fd);
4101 if (cmdline[1]) {
4102 cmdline[0] = '[';
4103 size_t len = strcspn(cmdline, "\f\b\r\n");
4104 cmdline[len] = ']';
4105 cmdline[len+1] = '\0';
4106 }
4107 }
4108 if (!cmdline[0]) {
4109 strcpy(cmdline, "N/A");
4110 }
4111 helper(pid, cmdline, arg);
4112 }
4113
4114 closedir(d);
4115}
4116
4117static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
4118 for_each_pid_func *func = (for_each_pid_func*) arg;
4119 func(pid, cmdline);
4120}
4121
4122void for_each_pid(for_each_pid_func func, const char *header) {
4123 std::string title = header == nullptr ? "for_each_pid"
4124 : android::base::StringPrintf("for_each_pid(%s)", header);
4125 DurationReporter duration_reporter(title);
4126 if (PropertiesHelper::IsDryRun()) return;
4127
4128 __for_each_pid(for_each_pid_helper, header, (void *) func);
4129}
4130
4131static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
4132 DIR *d;
4133 struct dirent *de;
4134 char taskpath[255];
4135 for_each_tid_func *func = (for_each_tid_func *) arg;
4136
4137 snprintf(taskpath, sizeof(taskpath), "/proc/%d/task", pid);
4138
4139 if (!(d = opendir(taskpath))) {
4140 printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
4141 return;
4142 }
4143
4144 func(pid, pid, cmdline);
4145
4146 while ((de = readdir(d))) {
4147 if (ds.IsUserConsentDenied()) {
4148 MYLOGE(
4149 "Returning early because user denied consent to share bugreport with calling app.");
4150 closedir(d);
4151 return;
4152 }
4153 int tid;
4154 int fd;
4155 char commpath[255];
4156 char comm[255];
4157
4158 if (!(tid = atoi(de->d_name))) {
4159 continue;
4160 }
4161
4162 if (tid == pid)
4163 continue;
4164
4165 snprintf(commpath, sizeof(commpath), "/proc/%d/comm", tid);
4166 memset(comm, 0, sizeof(comm));
4167 if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
4168 strcpy(comm, "N/A");
4169 } else {
4170 char *c;
4171 TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
4172 close(fd);
4173
4174 c = strrchr(comm, '\n');
4175 if (c) {
4176 *c = '\0';
4177 }
4178 }
4179 func(pid, tid, comm);
4180 }
4181
4182 closedir(d);
4183}
4184
4185void for_each_tid(for_each_tid_func func, const char *header) {
4186 std::string title = header == nullptr ? "for_each_tid"
4187 : android::base::StringPrintf("for_each_tid(%s)", header);
4188 DurationReporter duration_reporter(title);
4189
4190 if (PropertiesHelper::IsDryRun()) return;
4191
4192 __for_each_pid(for_each_tid_helper, header, (void *) func);
4193}
4194
4195void show_wchan(int pid, int tid, const char *name) {
4196 if (PropertiesHelper::IsDryRun()) return;
4197
4198 char path[255];
4199 char buffer[255];
4200 int fd, ret, save_errno;
4201 char name_buffer[255];
4202
4203 memset(buffer, 0, sizeof(buffer));
4204
4205 snprintf(path, sizeof(path), "/proc/%d/wchan", tid);
4206 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
4207 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
4208 return;
4209 }
4210
4211 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
4212 save_errno = errno;
4213 close(fd);
4214
4215 if (ret < 0) {
4216 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
4217 return;
4218 }
4219
4220 snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
4221 pid == tid ? 0 : 3, "", name);
4222
4223 printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
4224
4225 return;
4226}
4227
4228// print time in centiseconds
4229static void snprcent(char *buffer, size_t len, size_t spc,
4230 unsigned long long time) {
4231 static long hz; // cache discovered hz
4232
4233 if (hz <= 0) {
4234 hz = sysconf(_SC_CLK_TCK);
4235 if (hz <= 0) {
4236 hz = 1000;
4237 }
4238 }
4239
4240 // convert to centiseconds
4241 time = (time * 100 + (hz / 2)) / hz;
4242
4243 char str[16];
4244
4245 snprintf(str, sizeof(str), " %llu.%02u",
4246 time / 100, (unsigned)(time % 100));
4247 size_t offset = strlen(buffer);
4248 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
4249 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
4250}
4251
4252// print permille as a percent
4253static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
4254 char str[16];
4255
4256 snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
4257 size_t offset = strlen(buffer);
4258 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
4259 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
4260}
4261
4262void show_showtime(int pid, const char *name) {
4263 if (PropertiesHelper::IsDryRun()) return;
4264
4265 char path[255];
4266 char buffer[1023];
4267 int fd, ret, save_errno;
4268
4269 memset(buffer, 0, sizeof(buffer));
4270
4271 snprintf(path, sizeof(path), "/proc/%d/stat", pid);
4272 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
4273 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
4274 return;
4275 }
4276
4277 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
4278 save_errno = errno;
4279 close(fd);
4280
4281 if (ret < 0) {
4282 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
4283 return;
4284 }
4285
4286 // field 14 is utime
4287 // field 15 is stime
4288 // field 42 is iotime
4289 unsigned long long utime = 0, stime = 0, iotime = 0;
4290 if (sscanf(buffer,
4291 "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
4292 "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
4293 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
4294 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
4295 &utime, &stime, &iotime) != 3) {
4296 return;
4297 }
4298
4299 unsigned long long total = utime + stime;
4300 if (!total) {
4301 return;
4302 }
4303
4304 unsigned permille = (iotime * 1000 + (total / 2)) / total;
4305 if (permille > 1000) {
4306 permille = 1000;
4307 }
4308
4309 // try to beautify and stabilize columns at <80 characters
4310 snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
4311 if ((name[0] != '[') || utime) {
4312 snprcent(buffer, sizeof(buffer), 57, utime);
4313 }
4314 snprcent(buffer, sizeof(buffer), 65, stime);
4315 if ((name[0] != '[') || iotime) {
4316 snprcent(buffer, sizeof(buffer), 73, iotime);
4317 }
4318 if (iotime) {
4319 snprdec(buffer, sizeof(buffer), 79, permille);
4320 }
4321 puts(buffer); // adds a trailing newline
4322
4323 return;
4324}
4325
4326void do_dmesg() {
4327 const char *title = "KERNEL LOG (dmesg)";
4328 DurationReporter duration_reporter(title);
4329 printf("------ %s ------\n", title);
4330
4331 if (PropertiesHelper::IsDryRun()) return;
4332
4333 /* Get size of kernel buffer */
4334 int size = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
4335 if (size <= 0) {
4336 printf("Unexpected klogctl return value: %d\n\n", size);
4337 return;
4338 }
4339 char *buf = (char *) malloc(size + 1);
4340 if (buf == nullptr) {
4341 printf("memory allocation failed\n\n");
4342 return;
4343 }
4344 int retval = klogctl(KLOG_READ_ALL, buf, size);
4345 if (retval < 0) {
4346 printf("klogctl failure\n\n");
4347 free(buf);
4348 return;
4349 }
4350 buf[retval] = '\0';
4351 printf("%s\n\n", buf);
4352 free(buf);
4353 return;
4354}
4355
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004356int Dumpstate::DumpFile(const std::string& title, const std::string& path) {
4357 DurationReporter duration_reporter(title);
4358
4359 int status = DumpFileToFd(STDOUT_FILENO, title, path);
4360
4361 UpdateProgress(WEIGHT_FILE);
4362
4363 return status;
4364}
4365
4366int read_file_as_long(const char *path, long int *output) {
luoqiangwei15fcf2022024-03-07 15:29:20 +08004367 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
4368 if (fd.get() < 0) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004369 int err = errno;
4370 MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
4371 return -1;
4372 }
4373 char buffer[50];
luoqiangwei15fcf2022024-03-07 15:29:20 +08004374 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer, sizeof(buffer)));
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004375 if (bytes_read == -1) {
4376 MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
4377 return -2;
4378 }
4379 if (bytes_read == 0) {
4380 MYLOGE("File %s is empty\n", path);
4381 return -3;
4382 }
4383 *output = atoi(buffer);
4384 return 0;
4385}
4386
4387/* calls skip to gate calling dump_from_fd recursively
4388 * in the specified directory. dump_from_fd defaults to
4389 * dump_file_from_fd above when set to NULL. skip defaults
4390 * to false when set to NULL. dump_from_fd will always be
4391 * called with title NULL.
4392 */
4393int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
4394 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4395 DurationReporter duration_reporter(title);
4396 DIR *dirp;
4397 struct dirent *d;
4398 char *newpath = nullptr;
4399 const char *slash = "/";
4400 int retval = 0;
4401
4402 if (!title.empty()) {
4403 printf("------ %s (%s) ------\n", title.c_str(), dir);
4404 }
4405 if (PropertiesHelper::IsDryRun()) return 0;
4406
4407 if (dir[strlen(dir) - 1] == '/') {
4408 ++slash;
4409 }
4410 dirp = opendir(dir);
4411 if (dirp == nullptr) {
4412 retval = -errno;
4413 MYLOGE("%s: %s\n", dir, strerror(errno));
4414 return retval;
4415 }
4416
4417 if (!dump_from_fd) {
4418 dump_from_fd = dump_file_from_fd;
4419 }
4420 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4421 if ((d->d_name[0] == '.')
4422 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4423 || (d->d_name[1] == '\0'))) {
4424 continue;
4425 }
4426 asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
4427 (d->d_type == DT_DIR) ? "/" : "");
4428 if (!newpath) {
4429 retval = -errno;
4430 continue;
4431 }
4432 if (skip && (*skip)(newpath)) {
4433 continue;
4434 }
4435 if (d->d_type == DT_DIR) {
4436 int ret = dump_files("", newpath, skip, dump_from_fd);
4437 if (ret < 0) {
4438 retval = ret;
4439 }
4440 continue;
4441 }
4442 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
4443 if (fd.get() < 0) {
4444 retval = -1;
4445 printf("*** %s: %s\n", newpath, strerror(errno));
4446 continue;
4447 }
4448 (*dump_from_fd)(nullptr, newpath, fd.get());
4449 }
4450 closedir(dirp);
4451 if (!title.empty()) {
4452 printf("\n");
4453 }
4454 return retval;
4455}
4456
4457/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
4458 * it's possible to avoid issues where opening the file itself can get
4459 * stuck.
4460 */
4461int dump_file_from_fd(const char *title, const char *path, int fd) {
4462 if (PropertiesHelper::IsDryRun()) return 0;
4463
4464 int flags = fcntl(fd, F_GETFL);
4465 if (flags == -1) {
4466 printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
4467 return -1;
4468 } else if (!(flags & O_NONBLOCK)) {
4469 printf("*** %s: fd must have O_NONBLOCK set.\n", path);
4470 return -1;
4471 }
4472 return DumpFileFromFdToFd(title, path, fd, STDOUT_FILENO, PropertiesHelper::IsDryRun());
4473}
4474
4475int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004476 const CommandOptions& options, bool verbose_duration, int out_fd) {
4477 DurationReporter duration_reporter(title, false /* logcat_only */,
4478 verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004479
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004480 int status = RunCommandToFd(out_fd, title, full_command, options);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004481
4482 /* TODO: for now we're simplifying the progress calculation by using the
4483 * timeout as the weight. It's a good approximation for most cases, except when calling dumpsys,
4484 * where its weight should be much higher proportionally to its timeout.
4485 * Ideally, it should use a options.EstimatedDuration() instead...*/
4486 UpdateProgress(options.Timeout());
4487
4488 return status;
4489}
4490
4491void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
Rhed Jaoe017f982020-07-21 17:58:41 +08004492 const CommandOptions& options, long dumpsysTimeoutMs, int out_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004493 long timeout_ms = dumpsysTimeoutMs > 0 ? dumpsysTimeoutMs : options.TimeoutInMs();
4494 std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-T", std::to_string(timeout_ms)};
4495 dumpsys.insert(dumpsys.end(), dumpsys_args.begin(), dumpsys_args.end());
Rhed Jaoe017f982020-07-21 17:58:41 +08004496 RunCommand(title, dumpsys, options, false, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004497}
4498
Dieter Hsu105ad0c2020-09-29 15:23:33 +08004499static int open_socket(const char* service) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004500 int s = android_get_control_socket(service);
4501 if (s < 0) {
4502 MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
4503 return -1;
4504 }
4505 fcntl(s, F_SETFD, FD_CLOEXEC);
4506
4507 // Set backlog to 0 to make sure that queue size will be minimum.
4508 // In Linux, because the minimum queue will be 1, connect() will be blocked
4509 // if the other clients already called connect() and the connection request was not accepted.
4510 if (listen(s, 0) < 0) {
4511 MYLOGE("listen(control socket): %s\n", strerror(errno));
4512 return -1;
4513 }
4514
4515 struct sockaddr addr;
4516 socklen_t alen = sizeof(addr);
Abhijeet Kaur2113cae2019-09-13 09:24:15 +01004517 int fd = accept4(s, &addr, &alen, SOCK_CLOEXEC);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004518
4519 // Close socket just after accept(), to make sure that connect() by client will get error
4520 // when the socket is used by the other services.
4521 // There is still a race condition possibility between accept and close, but there is no way
4522 // to close-on-accept atomically.
4523 // See detail; b/123306389#comment25
4524 close(s);
4525
4526 if (fd < 0) {
4527 MYLOGE("accept(control socket): %s\n", strerror(errno));
4528 return -1;
4529 }
4530
4531 return fd;
4532}
4533
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004534// TODO: should call is_valid_output_file and/or be merged into it.
4535void create_parent_dirs(const char *path) {
4536 char *chp = const_cast<char *> (path);
4537
4538 /* skip initial slash */
4539 if (chp[0] == '/')
4540 chp++;
4541
4542 /* create leading directories, if necessary */
4543 struct stat dir_stat;
4544 while (chp && chp[0]) {
4545 chp = strchr(chp, '/');
4546 if (chp) {
4547 *chp = 0;
4548 if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
4549 MYLOGI("Creating directory %s\n", path);
4550 if (mkdir(path, 0770)) { /* drwxrwx--- */
4551 MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
4552 } else if (chown(path, AID_SHELL, AID_SHELL)) {
4553 MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
4554 }
4555 }
4556 *chp++ = '/';
4557 }
4558 }
4559}
4560
4561bool _redirect_to_file(FILE* redirect, char* path, int truncate_flag) {
4562 create_parent_dirs(path);
4563
4564 int fd = TEMP_FAILURE_RETRY(open(path,
4565 O_WRONLY | O_CREAT | truncate_flag | O_CLOEXEC | O_NOFOLLOW,
4566 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
4567 if (fd < 0) {
4568 MYLOGE("%s: %s\n", path, strerror(errno));
4569 return false;
4570 }
4571
4572 TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
4573 close(fd);
4574 return true;
4575}
4576
4577bool redirect_to_file(FILE* redirect, char* path) {
4578 return _redirect_to_file(redirect, path, O_TRUNC);
4579}
4580
4581bool redirect_to_existing_file(FILE* redirect, char* path) {
4582 return _redirect_to_file(redirect, path, O_APPEND);
4583}
4584
4585void dump_route_tables() {
4586 DurationReporter duration_reporter("DUMP ROUTE TABLES");
4587 if (PropertiesHelper::IsDryRun()) return;
4588 const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
4589 ds.DumpFile("RT_TABLES", RT_TABLES_PATH);
4590 FILE* fp = fopen(RT_TABLES_PATH, "re");
4591 if (!fp) {
4592 printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
4593 return;
4594 }
4595 char table[16];
4596 // Each line has an integer (the table number), a space, and a string (the table name). We only
4597 // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
4598 // Add a fixed max limit so this doesn't go awry.
4599 for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
4600 RunCommand("ROUTE TABLE IPv4", {"ip", "-4", "route", "show", "table", table});
4601 RunCommand("ROUTE TABLE IPv6", {"ip", "-6", "route", "show", "table", table});
4602 }
4603 fclose(fp);
4604}
4605
Li Li830179f2022-01-04 12:53:29 -08004606void dump_frozen_cgroupfs(const char *dir, int level,
4607 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4608 DIR *dirp;
4609 struct dirent *d;
4610 char *newpath = nullptr;
4611
4612 dirp = opendir(dir);
4613 if (dirp == nullptr) {
4614 MYLOGE("%s: %s\n", dir, strerror(errno));
4615 return;
4616 }
4617
4618 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4619 if ((d->d_name[0] == '.')
4620 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4621 || (d->d_name[1] == '\0'))) {
4622 continue;
4623 }
4624 if (d->d_type == DT_DIR) {
4625 asprintf(&newpath, "%s/%s/", dir, d->d_name);
4626 if (!newpath) {
4627 continue;
4628 }
4629 if (level == 0 && !strncmp(d->d_name, "uid_", 4)) {
4630 dump_frozen_cgroupfs(newpath, 1, dump_from_fd);
4631 } else if (level == 1 && !strncmp(d->d_name, "pid_", 4)) {
4632 char *freezer = nullptr;
4633 asprintf(&freezer, "%s/%s", newpath, "cgroup.freeze");
4634 if (freezer) {
4635 FILE* fp = fopen(freezer, "r");
4636 if (fp != NULL) {
4637 int frozen;
4638 fscanf(fp, "%d", &frozen);
4639 if (frozen > 0) {
4640 dump_files("", newpath, skip_none, dump_from_fd);
4641 }
4642 fclose(fp);
4643 }
4644 free(freezer);
4645 }
4646 }
4647 }
4648 }
4649 closedir(dirp);
4650}
4651
4652void dump_frozen_cgroupfs() {
Li Li830179f2022-01-04 12:53:29 -08004653 MYLOGD("Adding frozen processes from %s\n", CGROUPFS_DIR);
4654 DurationReporter duration_reporter("FROZEN CGROUPFS");
4655 if (PropertiesHelper::IsDryRun()) return;
4656 dump_frozen_cgroupfs(CGROUPFS_DIR, 0, _add_file_from_fd);
4657}
4658
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004659void Dumpstate::UpdateProgress(int32_t delta_sec) {
4660 if (progress_ == nullptr) {
4661 MYLOGE("UpdateProgress: progress_ not set\n");
4662 return;
4663 }
Rhed Jaobf63d8a2020-07-21 15:42:55 +08004664 // This function updates progress related members of the dumpstate and reports
4665 // progress percentage to the bugreport client. Since it could be called by
4666 // different dump tasks at the same time if the parallel run is enabled, a
4667 // mutex lock is necessary here to synchronize the call.
4668 std::lock_guard<std::recursive_mutex> lock(mutex_);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004669
4670 // Always update progess so stats can be tuned...
Nandana Dutt402a8392019-06-14 14:25:13 +01004671 progress_->Inc(delta_sec);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004672
4673 // ...but only notifiy listeners when necessary.
4674 if (!options_->do_progress_updates) return;
4675
4676 int progress = progress_->Get();
4677 int max = progress_->GetMax();
Nandana Dutt402a8392019-06-14 14:25:13 +01004678 int percent = 100 * progress / max;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004679
Nandana Dutt402a8392019-06-14 14:25:13 +01004680 if (last_reported_percent_progress_ > 0 && percent <= last_reported_percent_progress_) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004681 return;
4682 }
Nandana Dutt402a8392019-06-14 14:25:13 +01004683 last_reported_percent_progress_ = percent;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004684
4685 if (control_socket_fd_ >= 0) {
4686 dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
4687 fsync(control_socket_fd_);
4688 }
4689
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004690 if (listener_ != nullptr) {
Nandana Dutt235c6672019-11-14 15:22:32 +00004691 if (percent % 10 == 0) {
4692 // We don't want to spam logcat, so only log multiples of 10.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004693 MYLOGD("Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004694 } else {
4695 // stderr is ignored on normal invocations, but useful when calling
4696 // /system/bin/dumpstate directly for debuggging.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004697 fprintf(stderr, "Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004698 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004699
4700 listener_->onProgress(percent);
4701 }
4702}
4703
4704void Dumpstate::TakeScreenshot(const std::string& path) {
4705 const std::string& real_path = path.empty() ? screenshot_path_ : path;
4706 int status =
Abdelrahman Daim30e23602024-08-20 02:19:37 -07004707 RunCommand("", {"screencap", "-p", real_path},
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004708 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
4709 if (status == 0) {
4710 MYLOGD("Screenshot saved on %s\n", real_path.c_str());
4711 } else {
4712 MYLOGE("Failed to take screenshot on %s\n", real_path.c_str());
4713 }
Paul Chang0d2aad72020-02-13 20:04:03 +08004714 if (listener_ != nullptr) {
4715 // Show a visual indication to indicate screenshot is taken via
4716 // IDumpstateListener.onScreenshotTaken()
4717 listener_->onScreenshotTaken(status == 0);
4718 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004719}
4720
4721bool is_dir(const char* pathname) {
4722 struct stat info;
4723 if (stat(pathname, &info) == -1) {
4724 return false;
4725 }
4726 return S_ISDIR(info.st_mode);
4727}
4728
4729time_t get_mtime(int fd, time_t default_mtime) {
4730 struct stat info;
4731 if (fstat(fd, &info) == -1) {
4732 return default_mtime;
4733 }
4734 return info.st_mtime;
4735}