blob: 6576ffdc54ddea167edde262219476037e82117b [file] [log] [blame]
Colin Crossf45fa6b2012-03-26 12:38:26 -07001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Felipe Lemef0292972016-11-22 13:57:05 -080016
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070017#define LOG_TAG "dumpstate"
Kevin Jeon2c02e8e2022-07-07 21:45:17 +000018#define ATRACE_TAG ATRACE_TAG_ALWAYS
Colin Crossf45fa6b2012-03-26 12:38:26 -070019
Pablo Gamito654831c2024-02-16 16:47:48 +000020#include "dumpstate.h"
Colin Crossf45fa6b2012-03-26 12:38:26 -070021
Kedar Chitnis9fd8c052021-11-16 09:09:22 +000022#include <aidl/android/hardware/dumpstate/IDumpstateDevice.h>
Felipe Leme96c2bbb2016-09-26 09:21:21 -070023#include <android-base/file.h>
24#include <android-base/properties.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070025#include <android-base/scopeguard.h>
Elliott Hughes9dc117c2015-12-07 14:21:50 -080026#include <android-base/stringprintf.h>
Naveen Kalla058e1e82016-10-19 21:38:44 -070027#include <android-base/strings.h>
Andreas Gampeaff68432016-07-18 18:01:27 -070028#include <android-base/unique_fd.h>
Kedar Chitnis9fd8c052021-11-16 09:09:22 +000029#include <android/binder_manager.h>
30#include <android/binder_process.h>
Nikita Ioffea325a572019-05-16 19:49:47 +010031#include <android/content/pm/IPackageManagerNative.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080032#include <android/hardware/dumpstate/1.0/IDumpstateDevice.h>
Hunter Knepshield8540faf2020-02-04 19:47:20 -080033#include <android/hardware/dumpstate/1.1/IDumpstateDevice.h>
34#include <android/hardware/dumpstate/1.1/types.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080035#include <android/hidl/manager/1.0/IServiceManager.h>
Nandana Duttd2f5f082019-01-18 17:13:52 +000036#include <android/os/IIncidentCompanion.h>
Pablo Gamito654831c2024-02-16 16:47:48 +000037#include <android_app_admin_flags.h>
38#include <android_tracing.h>
Nikita Ioffea325a572019-05-16 19:49:47 +010039#include <binder/IServiceManager.h>
Nikhil Kumar28ce35e2023-01-10 14:32:44 +000040#include <cutils/multiuser.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080041#include <cutils/native_handle.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070042#include <cutils/properties.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010043#include <cutils/sockets.h>
Kevin Jeon2c02e8e2022-07-07 21:45:17 +000044#include <cutils/trace.h>
Nandana Duttfaafd522019-03-11 09:23:09 +000045#include <debuggerd/client.h>
Pablo Gamito654831c2024-02-16 16:47:48 +000046#include <dirent.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080047#include <dumpsys.h>
Nandana Duttfaafd522019-03-11 09:23:09 +000048#include <dumputils/dump_utils.h>
Pablo Gamito654831c2024-02-16 16:47:48 +000049#include <errno.h>
50#include <fcntl.h>
Sahana Raof35ed432019-07-12 10:47:52 +010051#include <hardware_legacy/power.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080052#include <hidl/ServiceManagement.h>
Pablo Gamito654831c2024-02-16 16:47:48 +000053#include <inttypes.h>
54#include <libgen.h>
55#include <limits.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010056#include <log/log.h>
Tom Cherryf4472f32020-08-05 09:31:17 -070057#include <log/log_read.h>
Pablo Gamito654831c2024-02-16 16:47:48 +000058#include <math.h>
Felipe Leme75876a22016-10-27 16:31:27 -070059#include <openssl/sha.h>
Pablo Gamito654831c2024-02-16 16:47:48 +000060#include <poll.h>
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070061#include <private/android_filesystem_config.h>
62#include <private/android_logger.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080063#include <serviceutils/PriorityDumper.h>
Pablo Gamito654831c2024-02-16 16:47:48 +000064#include <signal.h>
65#include <stdarg.h>
66#include <stdbool.h>
67#include <stdio.h>
68#include <stdlib.h>
69#include <string.h>
70#include <sys/capability.h>
71#include <sys/inotify.h>
72#include <sys/klog.h>
73#include <sys/mount.h>
74#include <sys/poll.h>
75#include <sys/prctl.h>
76#include <sys/resource.h>
77#include <sys/stat.h>
78#include <sys/time.h>
79#include <sys/wait.h>
80#include <time.h>
81#include <unistd.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070082#include <utils/StrongPointer.h>
Devin Moore8df81bb2022-06-08 22:47:02 +000083#include <vintf/VintfObject.h>
Pablo Gamito654831c2024-02-16 16:47:48 +000084
85#include <chrono>
86#include <cmath>
87#include <fstream>
88#include <functional>
89#include <future>
90#include <memory>
91#include <numeric>
92#include <regex>
93#include <set>
94#include <string>
95#include <utility>
96#include <vector>
97
Felipe Lemef0292972016-11-22 13:57:05 -080098#include "DumpstateInternal.h"
Felipe Leme75876a22016-10-27 16:31:27 -070099#include "DumpstateService.h"
Felipe Leme6e01fa62015-11-11 19:35:14 -0800100
Kedar Chitnis9fd8c052021-11-16 09:09:22 +0000101namespace dumpstate_hal_hidl_1_0 = android::hardware::dumpstate::V1_0;
102namespace dumpstate_hal_hidl = android::hardware::dumpstate::V1_1;
103namespace dumpstate_hal_aidl = aidl::android::hardware::dumpstate;
104
Vishnu Naire97d6122018-01-18 13:58:56 -0800105using ::std::literals::chrono_literals::operator""ms;
106using ::std::literals::chrono_literals::operator""s;
Rhed Jao5377d792020-07-16 17:37:39 +0800107using ::std::placeholders::_1;
Steven Morelandcb7ef822016-11-29 13:20:37 -0800108
Felipe Leme47e9be22016-12-21 15:37:07 -0800109// TODO: remove once moved to namespace
Vishnu Naire97d6122018-01-18 13:58:56 -0800110using android::defaultServiceManager;
111using android::Dumpsys;
112using android::INVALID_OPERATION;
113using android::IServiceManager;
114using android::OK;
115using android::sp;
116using android::status_t;
117using android::String16;
118using android::String8;
119using android::TIMED_OUT;
120using android::UNKNOWN_ERROR;
121using android::Vector;
Nandana Dutt979388e2018-11-30 16:48:55 +0000122using android::base::StringPrintf;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000123using android::os::IDumpstateListener;
Felipe Leme47e9be22016-12-21 15:37:07 -0800124using android::os::dumpstate::CommandOptions;
125using android::os::dumpstate::DumpFileToFd;
Rhed Jao5377d792020-07-16 17:37:39 +0800126using android::os::dumpstate::DumpPool;
Vishnu Naire97d6122018-01-18 13:58:56 -0800127using android::os::dumpstate::PropertiesHelper;
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800128using android::os::dumpstate::TaskQueue;
Chris Morinbc223142022-02-04 14:17:11 -0800129using android::os::dumpstate::WaitForTask;
Felipe Leme47e9be22016-12-21 15:37:07 -0800130
Abhijeet Kaurcf234e82019-07-01 14:53:55 +0100131// Keep in sync with
132// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
133static const int TRACE_DUMP_TIMEOUT_MS = 10000; // 10 seconds
134
135/* Most simple commands have 10 as timeout, so 5 is a good estimate */
136static const int32_t WEIGHT_FILE = 5;
137
138// TODO: temporary variables and functions used during C++ refactoring
139static Dumpstate& ds = Dumpstate::GetInstance();
140static int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Nandana Dutt8d945c02019-08-14 13:30:07 +0100141 const CommandOptions& options = CommandOptions::DEFAULT,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800142 bool verbose_duration = false, int out_fd = STDOUT_FILENO) {
143 return ds.RunCommand(title, full_command, options, verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +0100144}
145
146// Reasonable value for max stats.
147static const int STATS_MAX_N_RUNS = 1000;
148static const long STATS_MAX_AVERAGE = 100000;
149
150CommandOptions Dumpstate::DEFAULT_DUMPSYS = CommandOptions::WithTimeout(30).Build();
151
Nandana Duttd2f5f082019-01-18 17:13:52 +0000152typedef Dumpstate::ConsentCallback::ConsentResult UserConsentResult;
153
Colin Crossf45fa6b2012-03-26 12:38:26 -0700154/* read before root is shed */
155static char cmdline_buf[16384] = "(unknown)";
Yi Kong19d5c002018-07-20 13:39:55 -0700156static const char *dump_traces_path = nullptr;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000157static const uint64_t USER_CONSENT_TIMEOUT_MS = 30 * 1000;
Hunter Knepshield70610fa2020-01-03 15:27:33 -0800158// Because telephony reports are significantly faster to collect (< 10 seconds vs. > 2 minutes),
159// it's often the case that they time out far too quickly for consent with such a hefty dialog for
160// the user to read. For telephony reports only, we increase the default timeout to 2 minutes to
161// roughly match full reports' durations.
162static const uint64_t TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS = 2 * 60 * 1000;
Colin Crossf45fa6b2012-03-26 12:38:26 -0700163
Felipe Leme1d486fe2016-10-14 18:06:47 -0700164// TODO: variables and functions below should be part of dumpstate object
165
Felipe Leme635ca312016-01-05 14:23:02 -0800166static std::set<std::string> mount_points;
167void add_mountinfo();
Felipe Leme78f2c862015-12-21 09:55:22 -0800168
Todd Poynor2a83daa2013-11-22 15:44:22 -0800169#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
Mark Salyzyn7d0a7622016-06-24 14:06:15 -0700170#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
Wei Wang509bb5d2017-06-09 14:42:12 -0700171#define BLK_DEV_SYS_DIR "/sys/block"
Todd Poynor2a83daa2013-11-22 15:44:22 -0800172
Felipe Lemee82a27d2016-01-05 13:35:44 -0800173#define RECOVERY_DIR "/cache/recovery"
Mark Salyzynd6ab0112016-03-25 12:56:39 -0700174#define RECOVERY_DATA_DIR "/data/misc/recovery"
Tianjie Xu75d53362018-04-11 16:42:28 -0700175#define UPDATE_ENGINE_LOG_DIR "/data/misc/update_engine_log"
Kelvin Zhang6eaa0f92022-09-12 09:29:19 -0700176#define UPDATE_ENGINE_PREF_DIR "/data/misc/update_engine/prefs"
Mark Salyzyn4d42dea2016-04-01 10:03:14 -0700177#define LOGPERSIST_DATA_DIR "/data/misc/logd"
Jerry Changa1df8a92020-01-02 16:03:39 +0800178#define PREREBOOT_DATA_DIR "/data/misc/prereboot"
David Brazdild2991962016-06-03 14:40:44 +0100179#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
180#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
Benedict Wong8f9d8a42019-01-03 16:19:38 -0800181#define XFRM_STAT_PROC_FILE "/proc/net/xfrm_stat"
Steven Moreland9379c462023-12-21 02:04:27 +0000182#define KERNEL_CONFIG "/proc/config.gz"
Erik Kline08165202016-05-30 11:55:44 +0900183#define WLUTIL "/vendor/xbin/wlutil"
Vishnu Nair36b4cdb2017-11-17 10:27:05 -0800184#define WMTRACE_DATA_DIR "/data/misc/wmtrace"
Yifan Hong3945e1b2019-10-29 12:59:23 -0700185#define OTA_METADATA_DIR "/metadata/ota"
Yifan Hong0efa7972020-02-03 16:45:02 -0800186#define SNAPSHOTCTL_LOG_DIR "/data/misc/snapshotctl_log"
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +0900187#define LINKERCONFIG_DIR "/linkerconfig"
Calin Juravlef84d3692020-04-28 15:31:12 -0700188#define PACKAGE_DEX_USE_LIST "/data/system/package-dex-usage.list"
Primiano Tuccifaaaafb2021-01-14 12:26:29 +0000189#define SYSTEM_TRACE_SNAPSHOT "/data/misc/perfetto-traces/bugreport/systrace.pftrace"
Li Li2eedd412021-06-30 15:11:53 -0700190#define CGROUPFS_DIR "/sys/fs/cgroup"
MÃ¥rten Kongstad60195a72022-09-20 14:14:20 +0200191#define SDK_EXT_INFO "/apex/com.android.sdkext/bin/derive_sdk"
Jeff Sharkey9df29d52023-02-06 14:26:30 -0700192#define DROPBOX_DIR "/data/system/dropbox"
MÃ¥rten Kongstad5ad813f2023-09-28 10:09:18 +0200193#define PRINT_FLAGS "/system/bin/printflags"
Nattharat Jariyanuntanaetb250cae2024-05-15 07:48:19 +0000194#define UWB_LOG_DIR "/data/misc/apexdata/com.android.uwb/log"
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700195
Narayan Kamath8f788292017-05-25 13:20:39 +0100196// TODO(narayan): Since this information has to be kept in sync
197// with tombstoned, we should just put it in a common header.
198//
199// File: system/core/debuggerd/tombstoned/tombstoned.cpp
Narayan Kamathbd863722017-06-01 18:50:12 +0100200static const std::string TOMBSTONE_DIR = "/data/tombstones/";
201static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
202static const std::string ANR_DIR = "/data/anr/";
203static const std::string ANR_FILE_PREFIX = "anr_";
Andy Hungd62f7e62024-01-11 15:47:52 -0800204static const std::string ANR_TRACE_FILE_PREFIX = "trace_";
Woody Lin20767a92022-11-29 15:50:24 +0800205static const std::string SHUTDOWN_CHECKPOINTS_DIR = "/data/system/shutdown-checkpoints/";
206static const std::string SHUTDOWN_CHECKPOINTS_FILE_PREFIX = "checkpoints-";
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700207
Felipe Lemee844a9d2016-09-21 15:01:39 -0700208// TODO: temporary variables and functions used during C++ refactoring
Nandana Dutt979388e2018-11-30 16:48:55 +0000209
Nandana Dutt5c390032019-03-12 10:52:56 +0000210#define RETURN_IF_USER_DENIED_CONSENT() \
211 if (ds.IsUserConsentDenied()) { \
212 MYLOGE("Returning early as user denied consent to share bugreport with calling app."); \
213 return Dumpstate::RunStatus::USER_CONSENT_DENIED; \
214 }
215
216// Runs func_ptr, but checks user consent before and after running it. Returns USER_CONSENT_DENIED
217// if consent is found to be denied.
218#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(func_ptr, ...) \
219 RETURN_IF_USER_DENIED_CONSENT(); \
220 func_ptr(__VA_ARGS__); \
221 RETURN_IF_USER_DENIED_CONSENT();
222
Rhed Jao5377d792020-07-16 17:37:39 +0800223// Runs func_ptr, and logs a duration report after it's finished.
224#define RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, ...) \
225 { \
226 DurationReporter duration_reporter_in_macro(log_title); \
227 func_ptr(__VA_ARGS__); \
228 }
229
230// Similar with RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK, an additional duration report
231// is output after a slow function is finished.
232#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(log_title, func_ptr, ...) \
233 RETURN_IF_USER_DENIED_CONSENT(); \
234 RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, __VA_ARGS__); \
235 RETURN_IF_USER_DENIED_CONSENT();
236
Chris Morinbc223142022-02-04 14:17:11 -0800237#define WAIT_TASK_WITH_CONSENT_CHECK(future) \
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800238 RETURN_IF_USER_DENIED_CONSENT(); \
Chris Morinbc223142022-02-04 14:17:11 -0800239 WaitForTask(future); \
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800240 RETURN_IF_USER_DENIED_CONSENT();
241
Sahana Raof35ed432019-07-12 10:47:52 +0100242static const char* WAKE_LOCK_NAME = "dumpstate_wakelock";
243
Rhed Jao5377d792020-07-16 17:37:39 +0800244// Names of parallel tasks, they are used for the DumpPool to identify the dump
245// task and the log title of the duration report.
246static const std::string DUMP_TRACES_TASK = "DUMP TRACES";
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800247static const std::string DUMP_INCIDENT_REPORT_TASK = "INCIDENT REPORT";
Aaron Huang24d215d2022-04-27 18:51:16 +0800248static const std::string DUMP_NETSTATS_PROTO_TASK = "DUMP NETSTATS PROTO";
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800249static const std::string DUMP_HALS_TASK = "DUMP HALS";
250static const std::string DUMP_BOARD_TASK = "dumpstate_board()";
Rhed Jaoe017f982020-07-21 17:58:41 +0800251static const std::string DUMP_CHECKINS_TASK = "DUMP CHECKINS";
Kean Mariottica20f2d2023-12-15 09:34:25 +0000252static const std::string SERIALIZE_PERFETTO_TRACE_TASK = "SERIALIZE PERFETTO TRACE";
Rhed Jao5377d792020-07-16 17:37:39 +0800253
Nandana Dutt979388e2018-11-30 16:48:55 +0000254namespace android {
255namespace os {
256namespace {
257
258static int Open(std::string path, int flags, mode_t mode = 0) {
259 int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
260 if (fd == -1) {
261 MYLOGE("open(%s, %s)\n", path.c_str(), strerror(errno));
262 }
263 return fd;
264}
265
mhasank2d75c442020-06-11 15:05:25 -0700266static int OpenForWrite(std::string path) {
267 return Open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
268 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
269}
Nandana Dutt979388e2018-11-30 16:48:55 +0000270
271static int OpenForRead(std::string path) {
272 return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
273}
274
275bool CopyFile(int in_fd, int out_fd) {
276 char buf[4096];
277 ssize_t byte_count;
278 while ((byte_count = TEMP_FAILURE_RETRY(read(in_fd, buf, sizeof(buf)))) > 0) {
279 if (!android::base::WriteFully(out_fd, buf, byte_count)) {
280 return false;
281 }
282 }
283 return (byte_count != -1);
284}
285
286static bool CopyFileToFd(const std::string& input_file, int out_fd) {
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000287 MYLOGD("Going to copy file (%s) to %d\n", input_file.c_str(), out_fd);
Nandana Dutt979388e2018-11-30 16:48:55 +0000288
289 // Obtain a handle to the source file.
290 android::base::unique_fd in_fd(OpenForRead(input_file));
291 if (out_fd != -1 && in_fd.get() != -1) {
292 if (CopyFile(in_fd.get(), out_fd)) {
293 return true;
294 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000295 MYLOGE("Failed to copy file: %s\n", strerror(errno));
Nandana Dutt979388e2018-11-30 16:48:55 +0000296 }
297 return false;
298}
299
Nandana Duttd2f5f082019-01-18 17:13:52 +0000300static bool UnlinkAndLogOnError(const std::string& file) {
Nandana Dutt8ae16e62020-03-27 10:20:22 +0000301 if (file.empty()) {
302 return false;
303 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000304 if (unlink(file.c_str())) {
305 MYLOGE("Failed to unlink file (%s): %s\n", file.c_str(), strerror(errno));
Nandana Duttd2f5f082019-01-18 17:13:52 +0000306 return false;
307 }
308 return true;
309}
Nandana Dutt979388e2018-11-30 16:48:55 +0000310
Nikita Ioffea325a572019-05-16 19:49:47 +0100311int64_t GetModuleMetadataVersion() {
312 auto binder = defaultServiceManager()->getService(android::String16("package_native"));
313 if (binder == nullptr) {
314 MYLOGE("Failed to retrieve package_native service");
315 return 0L;
316 }
317 auto package_service = android::interface_cast<content::pm::IPackageManagerNative>(binder);
318 std::string package_name;
319 auto status = package_service->getModuleMetadataPackageName(&package_name);
320 if (!status.isOk()) {
321 MYLOGE("Failed to retrieve module metadata package name: %s", status.toString8().c_str());
322 return 0L;
323 }
Nandana Duttdb379fa2019-10-09 16:54:41 +0100324 MYLOGD("Module metadata package name: %s\n", package_name.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100325 int64_t version_code;
326 status = package_service->getVersionCodeForPackage(android::String16(package_name.c_str()),
327 &version_code);
328 if (!status.isOk()) {
329 MYLOGE("Failed to retrieve module metadata version: %s", status.toString8().c_str());
330 return 0L;
331 }
332 return version_code;
333}
334
mhasank2d75c442020-06-11 15:05:25 -0700335static bool PathExists(const std::string& path) {
336 struct stat sb;
337 return stat(path.c_str(), &sb) == 0;
338}
339
340static bool CopyFileToFile(const std::string& input_file, const std::string& output_file) {
341 if (input_file == output_file) {
342 MYLOGD("Skipping copying bugreport file since the destination is the same (%s)\n",
343 output_file.c_str());
344 return false;
345 }
346 else if (PathExists(output_file)) {
347 MYLOGD("Cannot overwrite an existing file (%s)\n", output_file.c_str());
348 return false;
349 }
350
351 MYLOGD("Going to copy bugreport file (%s) to %s\n", input_file.c_str(), output_file.c_str());
352 android::base::unique_fd out_fd(OpenForWrite(output_file));
353 return CopyFileToFd(input_file, out_fd.get());
354}
355
Nandana Dutt979388e2018-11-30 16:48:55 +0000356} // namespace
357} // namespace os
358} // namespace android
359
Felipe Leme678727a2016-09-21 17:22:11 -0700360static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
Felipe Lemebda15a02016-11-16 17:48:25 -0800361 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
Rhed Jaoe017f982020-07-21 17:58:41 +0800362 long dumpsysTimeoutMs = 0, int out_fd = STDOUT_FILENO) {
363 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs, out_fd);
364}
365static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
366 int out_fd) {
367 return ds.RunDumpsys(title, dumpsysArgs, Dumpstate::DEFAULT_DUMPSYS, 0, out_fd);
Felipe Leme678727a2016-09-21 17:22:11 -0700368}
369static int DumpFile(const std::string& title, const std::string& path) {
370 return ds.DumpFile(title, path);
371}
Felipe Lemee82a27d2016-01-05 13:35:44 -0800372
Felipe Lemee844a9d2016-09-21 15:01:39 -0700373// Relative directory (inside the zip) for all files copied as-is into the bugreport.
374static const std::string ZIP_ROOT_DIR = "FS";
375
Vishnu Naire97d6122018-01-18 13:58:56 -0800376static const std::string kProtoPath = "proto/";
377static const std::string kProtoExt = ".proto";
Jie Song9fbfad02017-06-20 16:29:42 -0700378static const std::string kDumpstateBoardFiles[] = {
379 "dumpstate_board.txt",
Felipe Leme95d6ca52017-08-01 16:35:56 -0700380 "dumpstate_board.bin"
Jie Song9fbfad02017-06-20 16:29:42 -0700381};
382static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
383
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700384static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Lemed071c682016-10-20 16:48:00 -0700385static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700386
Felipe Lemef0292972016-11-22 13:57:05 -0800387static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
388
Narayan Kamath8f788292017-05-25 13:20:39 +0100389/*
Narayan Kamathbd863722017-06-01 18:50:12 +0100390 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
Rhed Jao01dc0c62020-06-03 17:13:30 +0800391 * The returned vector is sorted by the mtimes of the dumps with descending
Chris Morinc2cba7a2022-02-01 17:06:50 -0800392 * order.
Narayan Kamath8f788292017-05-25 13:20:39 +0100393 */
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700394static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
Chris Morinc2cba7a2022-02-01 17:06:50 -0800395 const std::string& file_prefix) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100396 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100397
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700398 if (dump_dir == nullptr) {
399 MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno));
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700400 return std::vector<DumpData>();
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700401 }
402
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700403 std::vector<DumpData> dump_data;
Narayan Kamathbd863722017-06-01 18:50:12 +0100404 struct dirent* entry = nullptr;
405 while ((entry = readdir(dump_dir.get()))) {
406 if (entry->d_type != DT_REG) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100407 continue;
408 }
409
Narayan Kamathbd863722017-06-01 18:50:12 +0100410 const std::string base_name(entry->d_name);
411 if (base_name.find(file_prefix) != 0) {
412 continue;
413 }
414
415 const std::string abs_path = dir_path + base_name;
416 android::base::unique_fd fd(
417 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
418 if (fd == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700419 MYLOGW("Unable to open dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamathbd863722017-06-01 18:50:12 +0100420 break;
421 }
422
423 struct stat st = {};
424 if (fstat(fd, &st) == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700425 MYLOGW("Unable to stat dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamath8f788292017-05-25 13:20:39 +0100426 continue;
427 }
428
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700429 dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700430 }
Rhed Jao01dc0c62020-06-03 17:13:30 +0800431 if (!dump_data.empty()) {
432 std::sort(dump_data.begin(), dump_data.end(),
433 [](const auto& a, const auto& b) { return a.mtime > b.mtime; });
434 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100435
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700436 return dump_data;
Narayan Kamath8f788292017-05-25 13:20:39 +0100437}
438
Narayan Kamathbd863722017-06-01 18:50:12 +0100439static bool AddDumps(const std::vector<DumpData>::const_iterator start,
440 const std::vector<DumpData>::const_iterator end,
441 const char* type_name, const bool add_to_zip) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100442 bool dumped = false;
Narayan Kamathbd863722017-06-01 18:50:12 +0100443 for (auto it = start; it != end; ++it) {
444 const std::string& name = it->name;
445 const int fd = it->fd;
Narayan Kamath8f788292017-05-25 13:20:39 +0100446 dumped = true;
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100447
448 // Seek to the beginning of the file before dumping any data. A given
449 // DumpData entry might be dumped multiple times in the report.
450 //
451 // For example, the most recent ANR entry is dumped to the body of the
452 // main entry and it also shows up as a separate entry in the bugreport
453 // ZIP file.
454 if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) {
455 MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(),
456 strerror(errno));
457 }
458
Chris Morinc2cba7a2022-02-01 17:06:50 -0800459 if (add_to_zip) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800460 if (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd, /* timeout = */ 0ms) != OK) {
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100461 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100462 }
463 } else {
464 dump_file_from_fd(type_name, name.c_str(), fd);
465 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100466 }
467
468 return dumped;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700469}
470
Felipe Leme635ca312016-01-05 14:23:02 -0800471// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700472void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800473 char path[PATH_MAX];
474
475 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
476 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700477 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800478 char linkname[PATH_MAX];
479 ssize_t r = readlink(path, linkname, PATH_MAX);
480 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800481 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800482 return;
483 }
484 linkname[r] = '\0';
485
486 if (mount_points.find(linkname) == mount_points.end()) {
487 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700488 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700489 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
Felipe Leme635ca312016-01-05 14:23:02 -0800490 mount_points.insert(linkname);
491 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800492 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800493 }
494 }
495}
496
497void add_mountinfo() {
Felipe Leme678727a2016-09-21 17:22:11 -0700498 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800499 mount_points.clear();
Felipe Leme46b85da2016-11-21 17:40:45 -0800500 DurationReporter duration_reporter(title, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700501 for_each_pid(do_mountinfo, nullptr);
502 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800503}
504
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700505static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
506{
507 DIR *d;
508 struct dirent *de;
509 char path[PATH_MAX];
510
511 d = opendir(driverpath);
Yi Kong19d5c002018-07-20 13:39:55 -0700512 if (d == nullptr) {
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700513 return;
514 }
515
516 while ((de = readdir(d))) {
517 if (de->d_type != DT_LNK) {
518 continue;
519 }
520 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700521 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700522 }
523
524 closedir(d);
525}
526
Mark Salyzyn326842f2015-04-30 09:49:41 -0700527static bool skip_not_stat(const char *path) {
528 static const char stat[] = "/stat";
529 size_t len = strlen(path);
530 if (path[len - 1] == '/') { /* Directory? */
531 return false;
532 }
533 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
534}
535
Jeff Sharkey9df29d52023-02-06 14:26:30 -0700536static bool skip_wtf_strictmode(const char *path) {
537 if (strstr(path, "_wtf")) {
538 return true;
539 } else if (strstr(path, "_strictmode")) {
540 return true;
541 }
542 return false;
543}
544
Felipe Leme4c2d6632016-09-28 14:32:00 -0700545static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800546 return false;
547}
548
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700549unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700550
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800551//
552// stat offsets
553// Name units description
554// ---- ----- -----------
555// read I/Os requests number of read I/Os processed
556#define __STAT_READ_IOS 0
557// read merges requests number of read I/Os merged with in-queue I/O
558#define __STAT_READ_MERGES 1
559// read sectors sectors number of sectors read
560#define __STAT_READ_SECTORS 2
561// read ticks milliseconds total wait time for read requests
562#define __STAT_READ_TICKS 3
563// write I/Os requests number of write I/Os processed
564#define __STAT_WRITE_IOS 4
565// write merges requests number of write I/Os merged with in-queue I/O
566#define __STAT_WRITE_MERGES 5
567// write sectors sectors number of sectors written
568#define __STAT_WRITE_SECTORS 6
569// write ticks milliseconds total wait time for write requests
570#define __STAT_WRITE_TICKS 7
571// in_flight requests number of I/Os currently in flight
572#define __STAT_IN_FLIGHT 8
573// io_ticks milliseconds total time this block device has been active
574#define __STAT_IO_TICKS 9
575// time_in_queue milliseconds total wait time for all requests
576#define __STAT_IN_QUEUE 10
577#define __STAT_NUMBER_FIELD 11
578//
579// read I/Os, write I/Os
580// =====================
581//
582// These values increment when an I/O request completes.
583//
584// read merges, write merges
585// =========================
586//
587// These values increment when an I/O request is merged with an
588// already-queued I/O request.
589//
590// read sectors, write sectors
591// ===========================
592//
593// These values count the number of sectors read from or written to this
594// block device. The "sectors" in question are the standard UNIX 512-byte
595// sectors, not any device- or filesystem-specific block size. The
596// counters are incremented when the I/O completes.
597#define SECTOR_SIZE 512
598//
599// read ticks, write ticks
600// =======================
601//
602// These values count the number of milliseconds that I/O requests have
603// waited on this block device. If there are multiple I/O requests waiting,
604// these values will increase at a rate greater than 1000/second; for
605// example, if 60 read requests wait for an average of 30 ms, the read_ticks
606// field will increase by 60*30 = 1800.
607//
608// in_flight
609// =========
610//
611// This value counts the number of I/O requests that have been issued to
612// the device driver but have not yet completed. It does not include I/O
613// requests that are in the queue but not yet issued to the device driver.
614//
615// io_ticks
616// ========
617//
618// This value counts the number of milliseconds during which the device has
619// had I/O requests queued.
620//
621// time_in_queue
622// =============
623//
624// This value counts the number of milliseconds that I/O requests have waited
625// on this block device. If there are multiple I/O requests waiting, this
626// value will increase as the product of the number of milliseconds times the
627// number of requests waiting (see "read ticks" above for an example).
628#define S_TO_MS 1000
629//
630
Mark Salyzyn326842f2015-04-30 09:49:41 -0700631static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800632 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700633 bool z;
Yi Kong19d5c002018-07-20 13:39:55 -0700634 char *cp, *buffer = nullptr;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700635 size_t i = 0;
Josh Gao7c4258c2018-06-25 13:40:08 -0700636 FILE *fp = fdopen(dup(fd), "rb");
Mark Salyzyn326842f2015-04-30 09:49:41 -0700637 getline(&buffer, &i, fp);
638 fclose(fp);
639 if (!buffer) {
640 return -errno;
641 }
642 i = strlen(buffer);
643 while ((i > 0) && (buffer[i - 1] == '\n')) {
644 buffer[--i] = '\0';
645 }
646 if (!*buffer) {
647 free(buffer);
648 return 0;
649 }
650 z = true;
651 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800652 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700653 if (fields[i] != 0) {
654 z = false;
655 }
656 }
657 if (z) { /* never accessed */
658 free(buffer);
659 return 0;
660 }
661
Wei Wang509bb5d2017-06-09 14:42:12 -0700662 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
663 path += sizeof(BLK_DEV_SYS_DIR) - 1;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700664 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700665
666 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
667 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
668 "W-wait", "in-fli", "activ", "T-wait", path, buffer);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700669 free(buffer);
670
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800671 if (fields[__STAT_IO_TICKS]) {
672 unsigned long read_perf = 0;
673 unsigned long read_ios = 0;
674 if (fields[__STAT_READ_TICKS]) {
675 unsigned long long divisor = fields[__STAT_READ_TICKS]
676 * fields[__STAT_IO_TICKS];
677 read_perf = ((unsigned long long)SECTOR_SIZE
678 * fields[__STAT_READ_SECTORS]
679 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
680 / divisor;
681 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
682 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
683 / divisor;
684 }
685
686 unsigned long write_perf = 0;
687 unsigned long write_ios = 0;
688 if (fields[__STAT_WRITE_TICKS]) {
689 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
690 * fields[__STAT_IO_TICKS];
691 write_perf = ((unsigned long long)SECTOR_SIZE
692 * fields[__STAT_WRITE_SECTORS]
693 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
694 / divisor;
695 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
696 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
697 / divisor;
698 }
699
700 unsigned queue = (fields[__STAT_IN_QUEUE]
701 + (fields[__STAT_IO_TICKS] >> 1))
702 / fields[__STAT_IO_TICKS];
703
704 if (!write_perf && !write_ios) {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700705 printf("%-30s: perf(ios) rd: %luKB/s(%lu/s) q: %u\n", path, read_perf, read_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800706 } else {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700707 printf("%-30s: perf(ios) rd: %luKB/s(%lu/s) wr: %luKB/s(%lu/s) q: %u\n", path, read_perf,
Felipe Lemed8b94e52016-12-08 10:21:44 -0800708 read_ios, write_perf, write_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800709 }
710
711 /* bugreport timeout factor adjustment */
712 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
713 worst_write_perf = write_perf;
714 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700715 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700716 return 0;
717}
718
Yao Chenbe3bbc12018-01-17 16:31:10 -0800719static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
720
Tom Cherryf4472f32020-08-05 09:31:17 -0700721// Returns the actual readable size of the given buffer or -1 on error.
722static long logcat_buffer_readable_size(const std::string& buffer) {
723 std::unique_ptr<logger_list, decltype(&android_logger_list_free)> logger_list{
724 android_logger_list_alloc(0, 0, 0), &android_logger_list_free};
725 auto logger = android_logger_open(logger_list.get(), android_name_to_log_id(buffer.c_str()));
726
727 return android_logger_get_log_readable_size(logger);
728}
729
730// Returns timeout in ms to read a list of buffers.
Yao Chenbe3bbc12018-01-17 16:31:10 -0800731static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
732 unsigned long timeout_ms = 0;
733 for (const auto& buffer : buffers) {
Tom Cherryf4472f32020-08-05 09:31:17 -0700734 long readable_size = logcat_buffer_readable_size(buffer);
735 if (readable_size > 0) {
736 // Engineering margin is ten-fold our guess.
737 timeout_ms += 10 * (readable_size + worst_write_perf) / worst_write_perf;
738 }
Yao Chenbe3bbc12018-01-17 16:31:10 -0800739 }
740 return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700741}
742
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800743// Opens a socket and returns its file descriptor.
744static int open_socket(const char* service);
745
Nandana Duttd2f5f082019-01-18 17:13:52 +0000746Dumpstate::ConsentCallback::ConsentCallback() : result_(UNAVAILABLE), start_time_(Nanotime()) {
747}
748
749android::binder::Status Dumpstate::ConsentCallback::onReportApproved() {
750 std::lock_guard<std::mutex> lock(lock_);
751 result_ = APPROVED;
752 MYLOGD("User approved consent to share bugreport\n");
Paul Chang0d2aad72020-02-13 20:04:03 +0800753
754 // Maybe copy screenshot so calling app can display the screenshot to the user as soon as
755 // consent is granted.
756 if (ds.options_->is_screenshot_copied) {
757 return android::binder::Status::ok();
758 }
759
760 if (!ds.options_->do_screenshot || ds.options_->screenshot_fd.get() == -1 ||
761 !ds.do_early_screenshot_) {
762 return android::binder::Status::ok();
763 }
764
765 bool copy_succeeded = android::os::CopyFileToFd(ds.screenshot_path_,
766 ds.options_->screenshot_fd.get());
767 ds.options_->is_screenshot_copied = copy_succeeded;
768 if (copy_succeeded) {
769 android::os::UnlinkAndLogOnError(ds.screenshot_path_);
770 }
Nandana Duttd2f5f082019-01-18 17:13:52 +0000771 return android::binder::Status::ok();
772}
773
774android::binder::Status Dumpstate::ConsentCallback::onReportDenied() {
775 std::lock_guard<std::mutex> lock(lock_);
776 result_ = DENIED;
777 MYLOGW("User denied consent to share bugreport\n");
778 return android::binder::Status::ok();
779}
780
781UserConsentResult Dumpstate::ConsentCallback::getResult() {
782 std::lock_guard<std::mutex> lock(lock_);
783 return result_;
784}
785
786uint64_t Dumpstate::ConsentCallback::getElapsedTimeMs() const {
Hunter Knepshieldf0a39052020-01-03 14:53:04 -0800787 return (Nanotime() - start_time_) / NANOS_PER_MILLI;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000788}
789
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700790void Dumpstate::PrintHeader() const {
MÃ¥rten Kongstad60195a72022-09-20 14:14:20 +0200791 std::string build, fingerprint, radio, bootloader, network, sdkversion;
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700792 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700793
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700794 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
795 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700796 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
797 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
798 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
MÃ¥rten Kongstad60195a72022-09-20 14:14:20 +0200799 sdkversion = android::base::GetProperty("ro.build.version.sdk", "(unknown)");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700800 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
Colin Crossf45fa6b2012-03-26 12:38:26 -0700801
Felipe Lemed8b94e52016-12-08 10:21:44 -0800802 printf("========================================================\n");
803 printf("== dumpstate: %s\n", date);
804 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700805
Felipe Lemed8b94e52016-12-08 10:21:44 -0800806 printf("\n");
807 printf("Build: %s\n", build.c_str());
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700808 // NOTE: fingerprint entry format is important for other tools.
Felipe Lemed8b94e52016-12-08 10:21:44 -0800809 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
810 printf("Bootloader: %s\n", bootloader.c_str());
811 printf("Radio: %s\n", radio.c_str());
812 printf("Network: %s\n", network.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100813 int64_t module_metadata_version = android::os::GetModuleMetadataVersion();
814 if (module_metadata_version != 0) {
815 printf("Module Metadata version: %" PRId64 "\n", module_metadata_version);
816 }
MÃ¥rten Kongstad60195a72022-09-20 14:14:20 +0200817 printf("Android SDK version: %s\n", sdkversion.c_str());
818 printf("SDK extensions: ");
819 RunCommandToFd(STDOUT_FILENO, "", {SDK_EXT_INFO, "--header"},
820 CommandOptions::WithTimeout(1).Always().DropRoot().Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700821
Felipe Lemed8b94e52016-12-08 10:21:44 -0800822 printf("Kernel: ");
Felipe Lemef0292972016-11-22 13:57:05 -0800823 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
Felipe Lemed8b94e52016-12-08 10:21:44 -0800824 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
Devin Moore09fde8d2023-03-21 16:28:22 +0000825 printf("Bootconfig: ");
826 DumpFileToFd(STDOUT_FILENO, "", "/proc/bootconfig");
Felipe Leme7709f8a2017-12-05 09:30:09 -0800827 printf("Uptime: ");
828 RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"},
829 CommandOptions::WithTimeout(1).Always().Build());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800830 printf("Bugreport format version: %s\n", version_.c_str());
Kevin Jeonfa64e642023-07-27 11:36:41 -0400831 printf(
832 "Dumpstate info: id=%d pid=%d dry_run=%d parallel_run=%d strict_run=%d args=%s "
833 "bugreport_mode=%s\n",
834 id_, pid_, PropertiesHelper::IsDryRun(), PropertiesHelper::IsParallelRun(),
835 PropertiesHelper::IsStrictRun(), options_->args.c_str(),
836 options_->bugreport_mode_string.c_str());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800837 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800838}
839
Felipe Leme24b66ee2016-06-16 10:55:26 -0700840// List of file extensions that can cause a zip file attachment to be rejected by some email
841// service providers.
842static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
843 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
844 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
845 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
846};
847
Vishnu Naire97d6122018-01-18 13:58:56 -0800848status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd,
849 std::chrono::milliseconds timeout = 0ms) {
Felipe Leme24b66ee2016-06-16 10:55:26 -0700850 std::string valid_name = entry_name;
851
852 // Rename extension if necessary.
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -0700853 size_t idx = entry_name.rfind('.');
Felipe Leme24b66ee2016-06-16 10:55:26 -0700854 if (idx != std::string::npos) {
855 std::string extension = entry_name.substr(idx);
856 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
857 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
858 valid_name = entry_name + ".renamed";
859 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
860 }
861 }
862
Felipe Leme6fe9db62016-02-12 09:04:16 -0800863 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
864 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Kevin Jeon9bbe0ac2022-05-05 22:05:43 +0000865 size_t flags = ZipWriter::kCompress | ZipWriter::kDefaultCompression;
866 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), flags,
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700867 get_mtime(fd, ds.now_));
Felipe Leme1d486fe2016-10-14 18:06:47 -0700868 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700869 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700870 ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800871 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800872 }
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000873 bool finished_entry = false;
874 auto finish_entry = [this, &finished_entry] {
875 if (!finished_entry) {
876 // This should only be called when we're going to return an earlier error,
877 // which would've been logged. This may imply the file is already corrupt
878 // and any further logging from FinishEntry is more likely to mislead than
879 // not.
880 this->zip_writer_->FinishEntry();
881 }
882 };
883 auto scope_guard = android::base::make_scope_guard(finish_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -0800884 auto start = std::chrono::steady_clock::now();
885 auto end = start + timeout;
886 struct pollfd pfd = {fd, POLLIN};
Felipe Lemee82a27d2016-01-05 13:35:44 -0800887
Felipe Leme770410d2016-01-26 17:07:14 -0800888 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800889 while (1) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800890 if (timeout.count() > 0) {
891 // lambda to recalculate the timeout.
892 auto time_left_ms = [end]() {
893 auto now = std::chrono::steady_clock::now();
894 auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
895 return std::max(diff.count(), 0LL);
896 };
897
898 int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
899 if (rc < 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000900 MYLOGE("Error in poll while adding from fd to zip entry %s:%s\n",
901 entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800902 return -errno;
903 } else if (rc == 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000904 MYLOGE("Timed out adding from fd to zip entry %s:%s Timeout:%lldms\n",
Vishnu Naire97d6122018-01-18 13:58:56 -0800905 entry_name.c_str(), strerror(errno), timeout.count());
906 return TIMED_OUT;
907 }
908 }
909
Zach Riggle22200402016-08-18 01:01:24 -0400910 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800911 if (bytes_read == 0) {
912 break;
913 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800914 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800915 return -errno;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800916 }
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700917 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800918 if (err) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700919 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800920 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800921 }
922 }
923
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700924 err = zip_writer_->FinishEntry();
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000925 finished_entry = true;
Felipe Leme1d486fe2016-10-14 18:06:47 -0700926 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700927 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800928 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800929 }
930
Vishnu Naire97d6122018-01-18 13:58:56 -0800931 return OK;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800932}
933
Felipe Leme1d486fe2016-10-14 18:06:47 -0700934bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
935 android::base::unique_fd fd(
936 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700937 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800938 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800939 return false;
940 }
941
Vishnu Naire97d6122018-01-18 13:58:56 -0800942 return (AddZipEntryFromFd(entry_name, fd.get()) == OK);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800943}
944
945/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700946static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800947 return (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) == OK) ? 0 : 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800948}
949
Felipe Leme1d486fe2016-10-14 18:06:47 -0700950void Dumpstate::AddDir(const std::string& dir, bool recursive) {
Felipe Leme678727a2016-09-21 17:22:11 -0700951 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
Felipe Leme46b85da2016-11-21 17:40:45 -0800952 DurationReporter duration_reporter(dir, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700953 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800954}
955
Felipe Leme1d486fe2016-10-14 18:06:47 -0700956bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800957 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Kevin Jeon9bbe0ac2022-05-05 22:05:43 +0000958 size_t flags = ZipWriter::kCompress | ZipWriter::kDefaultCompression;
959 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), flags, ds.now_);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700960 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700961 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700962 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800963 return false;
964 }
965
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700966 err = zip_writer_->WriteBytes(content.c_str(), content.length());
Felipe Leme1d486fe2016-10-14 18:06:47 -0700967 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700968 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700969 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800970 return false;
971 }
972
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700973 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700974 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700975 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800976 return false;
977 }
978
979 return true;
980}
981
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800982static void DoKmsg() {
983 struct stat st;
984 if (!stat(PSTORE_LAST_KMSG, &st)) {
985 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
986 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
987 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
988 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
989 } else {
990 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
991 DumpFile("LAST KMSG", "/proc/last_kmsg");
992 }
993}
994
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800995static void DoKernelLogcat() {
Yao Chenbe3bbc12018-01-17 16:31:10 -0800996 unsigned long timeout_ms = logcat_timeout({"kernel"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800997 RunCommand(
998 "KERNEL LOG",
999 {"logcat", "-b", "kernel", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1000 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1001}
1002
Nandana Duttdb379fa2019-10-09 16:54:41 +01001003static void DoSystemLogcat(time_t since) {
1004 char since_str[80];
1005 strftime(since_str, sizeof(since_str), "%Y-%m-%d %H:%M:%S.000", localtime(&since));
1006
1007 unsigned long timeout_ms = logcat_timeout({"main", "system", "crash"});
1008 RunCommand("SYSTEM LOG",
1009 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v", "-T",
1010 since_str},
1011 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1012}
1013
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001014static void DoRadioLogcat() {
1015 unsigned long timeout_ms = logcat_timeout({"radio"});
1016 RunCommand(
1017 "RADIO LOG",
1018 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1019 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
1020}
1021
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001022static void DoLogcat() {
Vishnu Nair6921f802017-11-22 09:17:23 -08001023 unsigned long timeout_ms;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001024 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
1025 // calculate timeout
Yao Chenbe3bbc12018-01-17 16:31:10 -08001026 timeout_ms = logcat_timeout({"main", "system", "crash"});
Tony Makae737652017-03-30 17:47:09 +01001027 RunCommand("SYSTEM LOG",
Vishnu Nair6921f802017-11-22 09:17:23 -08001028 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1029 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -08001030 timeout_ms = logcat_timeout({"events"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001031 RunCommand(
1032 "EVENT LOG",
1033 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001034 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Yao Chenbe3bbc12018-01-17 16:31:10 -08001035 timeout_ms = logcat_timeout({"stats"});
1036 RunCommand(
1037 "STATS LOG",
1038 {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001039 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001040 DoRadioLogcat();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001041
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001042 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001043 RunCommand("LAST LOGCAT", {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable",
1044 "-v", "uid", "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001045}
1046
Mike Ma5c267872019-08-21 11:31:34 -07001047static void DumpIncidentReport() {
Mike Ma5c267872019-08-21 11:31:34 -07001048 const std::string path = ds.bugreport_internal_dir_ + "/tmp_incident_report";
1049 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1050 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1051 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1052 if (fd < 0) {
1053 MYLOGE("Could not open %s to dump incident report.\n", path.c_str());
1054 return;
1055 }
Kevin Jeonfa64e642023-07-27 11:36:41 -04001056 RunCommandToFd(fd, "", {"incident", "-u"},
1057 CommandOptions::WithTimeout(PropertiesHelper::IsStrictRun() ? 20 : 120).Build());
Mike Ma5c267872019-08-21 11:31:34 -07001058 bool empty = 0 == lseek(fd, 0, SEEK_END);
1059 if (!empty) {
1060 // Use a different name from "incident.proto"
1061 // /proto/incident.proto is reserved for incident service dump
1062 // i.e. metadata for debugging.
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001063 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "incident_report" + kProtoExt,
1064 path);
1065 } else {
1066 unlink(path.c_str());
Mike Ma5c267872019-08-21 11:31:34 -07001067 }
Mike Ma5c267872019-08-21 11:31:34 -07001068}
1069
Aaron Huang24d215d2022-04-27 18:51:16 +08001070static void DumpNetstatsProto() {
1071 const std::string path = ds.bugreport_internal_dir_ + "/tmp_netstats_proto";
1072 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1073 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1074 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1075 if (fd < 0) {
1076 MYLOGE("Could not open %s to dump netstats proto.\n", path.c_str());
1077 return;
1078 }
1079 RunCommandToFd(fd, "", {"dumpsys", "netstats", "--proto"},
Kevin Jeon2fb3dd62022-09-28 18:48:55 +00001080 CommandOptions::WithTimeout(5).Build());
Aaron Huang24d215d2022-04-27 18:51:16 +08001081 bool empty = 0 == lseek(fd, 0, SEEK_END);
1082 if (!empty) {
1083 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "netstats" + kProtoExt,
1084 path);
1085 } else {
1086 unlink(path.c_str());
1087 }
1088}
1089
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001090static void MaybeAddSystemTraceToZip() {
1091 // This function copies into the .zip the system trace that was snapshotted
Kean Mariottica20f2d2023-12-15 09:34:25 +00001092 // by the early call to MaybeSnapshotSystemTraceAsync(), if any background
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001093 // tracing was happening.
Kean Mariotti853b73a2023-07-27 12:40:30 +00001094 bool system_trace_exists = access(SYSTEM_TRACE_SNAPSHOT, F_OK) == 0;
1095 if (!system_trace_exists) {
Kean Mariottica20f2d2023-12-15 09:34:25 +00001096 // No background trace was happening at the time MaybeSnapshotSystemTraceAsync() was invoked
Kean Mariotti853b73a2023-07-27 12:40:30 +00001097 if (!PropertiesHelper::IsUserBuild()) {
1098 MYLOGI(
1099 "No system traces found. Check for previously uploaded traces by looking for "
1100 "go/trace-uuid in logcat")
1101 }
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001102 return;
1103 }
1104 ds.AddZipEntry(
1105 ZIP_ROOT_DIR + SYSTEM_TRACE_SNAPSHOT,
1106 SYSTEM_TRACE_SNAPSHOT);
1107 android::os::UnlinkAndLogOnError(SYSTEM_TRACE_SNAPSHOT);
1108}
1109
Sunny Goyal35949782019-11-19 15:54:36 -08001110static void DumpVisibleWindowViews() {
Sunny Goyal35949782019-11-19 15:54:36 -08001111 DurationReporter duration_reporter("VISIBLE WINDOW VIEWS");
1112 const std::string path = ds.bugreport_internal_dir_ + "/tmp_visible_window_views";
1113 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1114 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1115 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1116 if (fd < 0) {
1117 MYLOGE("Could not open %s to dump visible views.\n", path.c_str());
1118 return;
1119 }
1120 RunCommandToFd(fd, "", {"cmd", "window", "dump-visible-window-views"},
Kevin Jeon774abde2022-09-28 18:20:43 +00001121 CommandOptions::WithTimeout(10).Build());
Sunny Goyal35949782019-11-19 15:54:36 -08001122 bool empty = 0 == lseek(fd, 0, SEEK_END);
1123 if (!empty) {
1124 ds.AddZipEntry("visible_windows.zip", path);
1125 } else {
1126 MYLOGW("Failed to dump visible windows\n");
1127 }
1128 unlink(path.c_str());
1129}
1130
Jayachandran Ca94c7172017-06-10 15:08:12 -07001131static void DumpIpTablesAsRoot() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001132 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
1133 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +09001134 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001135 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +09001136 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
1137 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
1138 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
1139 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001140}
1141
Woody Lin20767a92022-11-29 15:50:24 +08001142static void DumpShutdownCheckpoints() {
1143 const bool shutdown_checkpoints_dumped = AddDumps(
1144 ds.shutdown_checkpoints_.begin(), ds.shutdown_checkpoints_.end(),
1145 "SHUTDOWN CHECKPOINTS", false /* add_to_zip */);
1146 if (!shutdown_checkpoints_dumped) {
1147 printf("*** NO SHUTDOWN CHECKPOINTS to dump in %s\n\n",
1148 SHUTDOWN_CHECKPOINTS_DIR.c_str());
1149 }
1150}
1151
David Andersond9ba4752018-12-11 18:26:59 -08001152static void DumpDynamicPartitionInfo() {
1153 if (!::android::base::GetBoolProperty("ro.boot.dynamic_partitions", false)) {
1154 return;
1155 }
1156
1157 RunCommand("LPDUMP", {"lpdump", "--all"});
David Anderson6650ade2019-10-02 15:18:59 -07001158 RunCommand("DEVICE-MAPPER", {"gsid", "dump-device-mapper"});
David Andersond9ba4752018-12-11 18:26:59 -08001159}
1160
Chris Morin5a50d482022-02-01 17:41:18 -08001161static void AddAnrTraceDir(const std::string& anr_traces_dir) {
Narayan Kamath8f788292017-05-25 13:20:39 +01001162 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
1163 anr_traces_dir.c_str());
1164
1165 // If we're here, dump_traces_path will always be a temporary file
1166 // (created with mkostemp or similar) that contains dumps taken earlier
1167 // on in the process.
1168 if (dump_traces_path != nullptr) {
Chris Morin5a50d482022-02-01 17:41:18 -08001169 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
1170 dump_traces_path);
1171 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
Narayan Kamath8f788292017-05-25 13:20:39 +01001172
1173 const int ret = unlink(dump_traces_path);
1174 if (ret == -1) {
1175 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
1176 strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -07001177 }
1178 }
1179
Narayan Kamathbd863722017-06-01 18:50:12 +01001180 // Add a specific message for the first ANR Dump.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001181 if (ds.anr_data_.size() > 0) {
Chris Morin5a50d482022-02-01 17:41:18 -08001182 // The "last" ANR will always be present in the body of the main entry.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001183 AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1,
Chris Morin5a50d482022-02-01 17:41:18 -08001184 "VM TRACES AT LAST ANR", false /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001185
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001186 // Historical ANRs are always included as separate entries in the bugreport zip file.
Chris Morin5a50d482022-02-01 17:41:18 -08001187 AddDumps(ds.anr_data_.begin(), ds.anr_data_.end(),
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001188 "HISTORICAL ANR", true /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001189 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +01001190 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
1191 }
Andy Hungd62f7e62024-01-11 15:47:52 -08001192
1193 // Add Java anr traces (such as generated by the Finalizer Watchdog).
1194 AddDumps(ds.anr_trace_data_.begin(), ds.anr_trace_data_.end(), "JAVA ANR TRACES",
1195 true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001196}
1197
1198static void AddAnrTraceFiles() {
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001199 std::string anr_traces_dir = "/data/anr";
Narayan Kamath8f788292017-05-25 13:20:39 +01001200
Chris Morin5a50d482022-02-01 17:41:18 -08001201 AddAnrTraceDir(anr_traces_dir);
Narayan Kamath8f788292017-05-25 13:20:39 +01001202
Makoto Onuki83ec63f2019-01-31 17:08:59 -08001203 RunCommand("ANR FILES", {"ls", "-lt", ANR_DIR});
1204
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001205 // Slow traces for slow operations.
Felipe Lemee184f662016-10-27 10:04:47 -07001206 struct stat st;
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001207 int i = 0;
1208 while (true) {
1209 const std::string slow_trace_path =
1210 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
1211 if (stat(slow_trace_path.c_str(), &st)) {
1212 // No traces file at this index, done with the files.
1213 break;
Felipe Lemee184f662016-10-27 10:04:47 -07001214 }
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001215 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
1216 i++;
Felipe Lemee184f662016-10-27 10:04:47 -07001217 }
1218}
1219
Wei Wang509bb5d2017-06-09 14:42:12 -07001220static void DumpBlockStatFiles() {
1221 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -07001222
Wei Wang1dc1ef52017-06-12 11:28:37 -07001223 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
1224
1225 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001226 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1227 return;
1228 }
1229
1230 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -07001231 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001232 if ((d->d_name[0] == '.')
1233 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1234 || (d->d_name[1] == '\0'))) {
1235 continue;
1236 }
1237 const std::string new_path =
1238 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1239 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1240 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1241 printf("\n");
1242 }
Wei Wang1dc1ef52017-06-12 11:28:37 -07001243 return;
Wei Wang509bb5d2017-06-09 14:42:12 -07001244}
Jayachandran Ca94c7172017-06-10 15:08:12 -07001245
1246static void DumpPacketStats() {
1247 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
Jayachandran Ca94c7172017-06-10 15:08:12 -07001248}
1249
1250static void DumpIpAddrAndRules() {
1251 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
Ray Chencbf278a2023-11-20 07:49:45 +00001252 RunCommand("NETWORK INTERFACES", {"ip", "-s", "link"});
Jayachandran Ca94c7172017-06-10 15:08:12 -07001253 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1254 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1255 RunCommand("IP RULES", {"ip", "rule", "show"});
1256 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1257}
1258
Nandana Dutt5c390032019-03-12 10:52:56 +00001259static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, int priority,
1260 std::chrono::milliseconds timeout,
1261 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001262 auto start = std::chrono::steady_clock::now();
Vishnu Naire97d6122018-01-18 13:58:56 -08001263 sp<android::IServiceManager> sm = defaultServiceManager();
1264 Dumpsys dumpsys(sm.get());
Vishnu Naire97d6122018-01-18 13:58:56 -08001265 Vector<String16> args;
1266 Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
Vishnu Naire97d6122018-01-18 13:58:56 -08001267 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1268 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001269 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001270 std::string path(title);
1271 path.append(" - ").append(String8(service).c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -08001272 size_t bytes_written = 0;
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001273 if (PropertiesHelper::IsDryRun()) {
1274 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1275 dumpsys.writeDumpFooter(STDOUT_FILENO, service, std::chrono::milliseconds(1));
1276 } else {
Devin Mooref492c1a2023-03-15 19:19:03 +00001277 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP | Dumpsys::TYPE_PID |
1278 Dumpsys::TYPE_CLIENTS | Dumpsys::TYPE_THREAD,
Devin Mooreae68df22023-02-24 20:59:51 +00001279 service, args);
1280 if (status == OK) {
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001281 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1282 std::chrono::duration<double> elapsed_seconds;
1283 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH &&
1284 service == String16("meminfo")) {
1285 // Use a longer timeout for meminfo, since 30s is not always enough.
1286 status = dumpsys.writeDump(STDOUT_FILENO, service, 60s,
1287 /* as_proto = */ false, elapsed_seconds,
1288 bytes_written);
1289 } else {
1290 status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
1291 /* as_proto = */ false, elapsed_seconds,
1292 bytes_written);
1293 }
1294 dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
1295 bool dump_complete = (status == OK);
1296 dumpsys.stopDumpThread(dump_complete);
Devin Moorecdfa4602023-03-16 20:49:39 +00001297 } else {
1298 MYLOGE("Failed to start dump thread for service: %s, status: %d",
1299 String8(service).c_str(), status);
Gavin Corkeryfac7e2b2021-07-08 22:39:02 +01001300 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001301 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001302
1303 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1304 std::chrono::steady_clock::now() - start);
1305 if (elapsed_duration > timeout) {
1306 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1307 elapsed_duration.count());
1308 break;
1309 }
1310 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001311 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001312}
1313
Vishnu Nair64afc022018-02-01 15:29:34 -08001314static void RunDumpsysText(const std::string& title, int priority,
1315 std::chrono::milliseconds timeout,
1316 std::chrono::milliseconds service_timeout) {
1317 DurationReporter duration_reporter(title);
1318 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1319 fsync(STDOUT_FILENO);
1320 RunDumpsysTextByPriority(title, priority, timeout, service_timeout);
1321}
1322
1323/* Dump all services registered with Normal or Default priority. */
Nandana Dutt5c390032019-03-12 10:52:56 +00001324static Dumpstate::RunStatus RunDumpsysTextNormalPriority(const std::string& title,
1325 std::chrono::milliseconds timeout,
1326 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001327 DurationReporter duration_reporter(title);
1328 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1329 fsync(STDOUT_FILENO);
1330 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout,
1331 service_timeout);
Nandana Dutt5c390032019-03-12 10:52:56 +00001332
1333 RETURN_IF_USER_DENIED_CONSENT();
1334
1335 return RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1336 service_timeout);
Vishnu Nair64afc022018-02-01 15:29:34 -08001337}
1338
Nandana Dutt5c390032019-03-12 10:52:56 +00001339static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priority,
1340 std::chrono::milliseconds timeout,
1341 std::chrono::milliseconds service_timeout) {
Vishnu Naire97d6122018-01-18 13:58:56 -08001342 sp<android::IServiceManager> sm = defaultServiceManager();
1343 Dumpsys dumpsys(sm.get());
1344 Vector<String16> args;
1345 Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
1346 DurationReporter duration_reporter(title);
1347
1348 auto start = std::chrono::steady_clock::now();
1349 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
1350 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001351 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001352 std::string path(kProtoPath);
1353 path.append(String8(service).c_str());
1354 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
1355 path.append("_CRITICAL");
1356 } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
1357 path.append("_HIGH");
1358 }
1359 path.append(kProtoExt);
Steven Morelandcbd69fc2021-07-20 20:45:43 +00001360 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP, service, args);
Vishnu Naire97d6122018-01-18 13:58:56 -08001361 if (status == OK) {
1362 status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
1363 bool dumpTerminated = (status == OK);
1364 dumpsys.stopDumpThread(dumpTerminated);
1365 }
1366 ZipWriter::FileEntry file_entry;
1367 ds.zip_writer_->GetLastEntry(&file_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -08001368
1369 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1370 std::chrono::steady_clock::now() - start);
1371 if (elapsed_duration > timeout) {
1372 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1373 elapsed_duration.count());
1374 break;
1375 }
1376 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001377 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001378}
1379
Nandana Dutta7db6342018-11-21 14:53:34 +00001380// Runs dumpsys on services that must dump first and will take less than 100ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001381static Dumpstate::RunStatus RunDumpsysCritical() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001382 RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1383 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Nandana Dutt5c390032019-03-12 10:52:56 +00001384
1385 RETURN_IF_USER_DENIED_CONSENT();
1386
1387 return RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1388 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Vishnu Nair780b1282017-10-10 13:57:24 -07001389}
1390
1391// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001392static Dumpstate::RunStatus RunDumpsysHigh() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001393 // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
1394 // high priority. Reduce timeout once they are able to dump in a shorter time or
1395 // moved to a parallel task.
1396 RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1397 /* timeout= */ 90s, /* service_timeout= */ 30s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001398
1399 RETURN_IF_USER_DENIED_CONSENT();
1400
1401 return RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1402 /* timeout= */ 5s, /* service_timeout= */ 1s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001403}
1404
1405// Runs dumpsys on services that must dump but can take up to 10s to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001406static Dumpstate::RunStatus RunDumpsysNormal() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001407 RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001408
1409 RETURN_IF_USER_DENIED_CONSENT();
1410
1411 return RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1412 /* timeout= */ 90s, /* service_timeout= */ 10s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001413}
1414
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001415/*
1416 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1417 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1418 * if it's not running in the parallel task.
1419 */
1420static void DumpHals(int out_fd = STDOUT_FILENO) {
Yifan Hong30528a22020-08-07 18:24:06 -07001421 RunCommand("HARDWARE HALS", {"lshal", "--all", "--types=all"},
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001422 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build(),
1423 false, out_fd);
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001424
Steven Moreland44cd9482018-01-04 16:24:13 -08001425 using android::hidl::manager::V1_0::IServiceManager;
1426 using android::hardware::defaultServiceManager;
1427
1428 sp<IServiceManager> sm = defaultServiceManager();
1429 if (sm == nullptr) {
1430 MYLOGE("Could not retrieve hwservicemanager to dump hals.\n");
1431 return;
1432 }
1433
1434 auto ret = sm->list([&](const auto& interfaces) {
1435 for (const std::string& interface : interfaces) {
1436 std::string cleanName = interface;
Steven Morelandc6b1fc22023-07-26 23:53:58 +00001437 std::replace_if(
1438 cleanName.begin(), cleanName.end(),
1439 [](char c) {
1440 return !isalnum(c) && std::string("@-_.").find(c) == std::string::npos;
1441 },
1442 '_');
Nandana Dutt979388e2018-11-30 16:48:55 +00001443 const std::string path = ds.bugreport_internal_dir_ + "/lshal_debug_" + cleanName;
Steven Moreland44cd9482018-01-04 16:24:13 -08001444
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001445 bool empty = false;
Steven Moreland44cd9482018-01-04 16:24:13 -08001446 {
1447 auto fd = android::base::unique_fd(
1448 TEMP_FAILURE_RETRY(open(path.c_str(),
1449 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1450 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1451 if (fd < 0) {
1452 MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str());
1453 continue;
1454 }
1455 RunCommandToFd(fd,
1456 "",
Steven Morelandc81cd3c2018-01-18 14:36:26 -08001457 {"lshal", "debug", "-E", interface},
Steven Moreland44cd9482018-01-04 16:24:13 -08001458 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1459
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001460 empty = 0 == lseek(fd, 0, SEEK_END);
Steven Moreland44cd9482018-01-04 16:24:13 -08001461 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001462 if (!empty) {
1463 ds.EnqueueAddZipEntryAndCleanupIfNeeded("lshal-debug/" + cleanName + ".txt",
1464 path);
1465 } else {
1466 unlink(path.c_str());
1467 }
Steven Moreland44cd9482018-01-04 16:24:13 -08001468 }
1469 });
1470
1471 if (!ret.isOk()) {
1472 MYLOGE("Could not list hals from hwservicemanager.\n");
1473 }
1474}
1475
Devin Moore8df81bb2022-06-08 22:47:02 +00001476// Dump all of the files that make up the vendor interface.
1477// See the files listed in dumpFileList() for the latest list of files.
1478static void DumpVintf() {
Devin Moore16271d92022-09-22 18:28:48 +00001479
1480 const std::string sku = android::base::GetProperty("ro.boot.product.hardware.sku", "");
1481 const auto vintfFiles = android::vintf::details::dumpFileList(sku);
Devin Moore8df81bb2022-06-08 22:47:02 +00001482 for (const auto vintfFile : vintfFiles) {
1483 struct stat st;
1484 if (stat(vintfFile.c_str(), &st) == 0) {
1485 if (S_ISDIR(st.st_mode)) {
1486 ds.AddDir(vintfFile, true /* recursive */);
1487 } else {
1488 ds.EnqueueAddZipEntryAndCleanupIfNeeded(ZIP_ROOT_DIR + vintfFile,
1489 vintfFile);
1490 }
1491 }
1492 }
1493}
1494
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001495static void DumpExternalFragmentationInfo() {
1496 struct stat st;
1497 if (stat("/proc/buddyinfo", &st) != 0) {
1498 MYLOGE("Unable to dump external fragmentation info\n");
1499 return;
1500 }
1501
1502 printf("------ EXTERNAL FRAGMENTATION INFO ------\n");
1503 std::ifstream ifs("/proc/buddyinfo");
1504 auto unusable_index_regex = std::regex{"Node\\s+([0-9]+),\\s+zone\\s+(\\S+)\\s+(.*)"};
1505 for (std::string line; std::getline(ifs, line);) {
1506 std::smatch match_results;
1507 if (std::regex_match(line, match_results, unusable_index_regex)) {
1508 std::stringstream free_pages(std::string{match_results[3]});
1509 std::vector<int> free_pages_per_order(std::istream_iterator<int>{free_pages},
1510 std::istream_iterator<int>());
1511
1512 int total_free_pages = 0;
1513 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1514 total_free_pages += (free_pages_per_order[i] * std::pow(2, i));
1515 }
1516
1517 printf("Node %s, zone %8s", match_results[1].str().c_str(),
1518 match_results[2].str().c_str());
1519
1520 int usable_free_pages = total_free_pages;
1521 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1522 auto unusable_index = (total_free_pages - usable_free_pages) /
1523 static_cast<double>(total_free_pages);
1524 printf(" %5.3f", unusable_index);
1525 usable_free_pages -= (free_pages_per_order[i] * std::pow(2, i));
1526 }
1527
1528 printf("\n");
1529 }
1530 }
1531 printf("\n");
1532}
1533
mhasankd451a472020-05-26 18:02:39 -07001534static void DumpstateLimitedOnly() {
EdenSue8fe4522023-11-20 15:37:23 +08001535 // Trimmed-down version of dumpstate to only include a allowlisted
mhasankd451a472020-05-26 18:02:39 -07001536 // set of logs (system log, event log, and system server / system app
1537 // crashes, and networking logs). See b/136273873 and b/138459828
1538 // for context.
1539 DurationReporter duration_reporter("DUMPSTATE");
1540 unsigned long timeout_ms;
1541 // calculate timeout
1542 timeout_ms = logcat_timeout({"main", "system", "crash"});
1543 RunCommand("SYSTEM LOG",
1544 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1545 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1546 timeout_ms = logcat_timeout({"events"});
1547 RunCommand(
1548 "EVENT LOG",
1549 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1550 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1551
1552 printf("========================================================\n");
1553 printf("== Networking Service\n");
1554 printf("========================================================\n");
1555
1556 RunDumpsys("DUMPSYS NETWORK_SERVICE_LIMITED", {"wifi", "-a"},
1557 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hugo Benichiaa162682020-10-30 23:28:56 +09001558 RunDumpsys("DUMPSYS CONNECTIVITY REQUESTS", {"connectivity", "requests"},
1559 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
mhasankd451a472020-05-26 18:02:39 -07001560
1561 printf("========================================================\n");
1562 printf("== Dropbox crashes\n");
1563 printf("========================================================\n");
1564
1565 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1566 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1567
Bryan Yuefb85d92024-02-02 13:37:06 +00001568
1569 printf("========================================================\n");
1570 printf("== ANR Traces\n");
1571 printf("========================================================\n");
1572
Bryan Yucf038cf2024-05-08 09:25:25 +00001573 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX);
Bryan Yuefb85d92024-02-02 13:37:06 +00001574 AddAnrTraceFiles();
1575
mhasankd451a472020-05-26 18:02:39 -07001576 printf("========================================================\n");
1577 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1578 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1579 printf("========================================================\n");
1580 printf("== dumpstate: done (id %d)\n", ds.id_);
1581 printf("========================================================\n");
1582}
1583
Rhed Jaoe017f982020-07-21 17:58:41 +08001584/*
1585 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1586 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1587 * if it's not running in the parallel task.
1588 */
1589static void DumpCheckins(int out_fd = STDOUT_FILENO) {
1590 dprintf(out_fd, "========================================================\n");
1591 dprintf(out_fd, "== Checkins\n");
1592 dprintf(out_fd, "========================================================\n");
1593
1594 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"}, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001595 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"}, out_fd);
1596 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"}, out_fd);
1597 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"}, out_fd);
1598 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"}, out_fd);
1599}
1600
1601/*
1602 * Runs dumpsys on activity service to dump all application activities, services
1603 * and providers in the device.
1604 *
1605 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1606 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1607 * if it's not running in the parallel task.
1608 */
1609static void DumpAppInfos(int out_fd = STDOUT_FILENO) {
1610 dprintf(out_fd, "========================================================\n");
1611 dprintf(out_fd, "== Running Application Activities\n");
1612 dprintf(out_fd, "========================================================\n");
1613
1614 // The following dumpsys internally collects output from running apps, so it can take a long
1615 // time. So let's extend the timeout.
1616
1617 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1618
1619 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1620
1621 dprintf(out_fd, "========================================================\n");
1622 dprintf(out_fd, "== Running Application Services (platform)\n");
1623 dprintf(out_fd, "========================================================\n");
1624
1625 RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
1626 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1627
1628 dprintf(out_fd, "========================================================\n");
1629 dprintf(out_fd, "== Running Application Services (non-platform)\n");
1630 dprintf(out_fd, "========================================================\n");
1631
1632 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1633 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1634
1635 dprintf(out_fd, "========================================================\n");
1636 dprintf(out_fd, "== Running Application Providers (platform)\n");
1637 dprintf(out_fd, "========================================================\n");
1638
1639 RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
Rhed Jaob049f182021-01-11 21:08:43 +08001640 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001641
1642 dprintf(out_fd, "========================================================\n");
1643 dprintf(out_fd, "== Running Application Providers (non-platform)\n");
1644 dprintf(out_fd, "========================================================\n");
1645
1646 RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1647 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1648}
1649
Nandana Dutt5c390032019-03-12 10:52:56 +00001650// Dumps various things. Returns early with status USER_CONSENT_DENIED if user denies consent
1651// via the consent they are shown. Ignores other errors that occur while running various
1652// commands. The consent checking is currently done around long running tasks, which happen to
1653// be distributed fairly evenly throughout the function.
Kean Mariotti306633e2022-09-05 16:30:47 +00001654Dumpstate::RunStatus Dumpstate::dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001655 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001656
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001657 // Enqueue slow functions into the thread pool, if the parallel run is enabled.
Aaron Huang24d215d2022-04-27 18:51:16 +08001658 std::future<std::string> dump_hals, dump_incident_report, dump_board, dump_checkins,
Kean Mariottica20f2d2023-12-15 09:34:25 +00001659 dump_netstats_report;
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001660 if (ds.dump_pool_) {
1661 // Pool was shutdown in DumpstateDefaultAfterCritical method in order to
Kean Mariotti306633e2022-09-05 16:30:47 +00001662 // drop root user. Restarts it.
1663 ds.dump_pool_->start(/* thread_counts = */3);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001664
Chris Morinbc223142022-02-04 14:17:11 -08001665 dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
1666 dump_incident_report = ds.dump_pool_->enqueueTask(
1667 DUMP_INCIDENT_REPORT_TASK, &DumpIncidentReport);
Aaron Huang24d215d2022-04-27 18:51:16 +08001668 dump_netstats_report = ds.dump_pool_->enqueueTask(
1669 DUMP_NETSTATS_PROTO_TASK, &DumpNetstatsProto);
Chris Morinbc223142022-02-04 14:17:11 -08001670 dump_board = ds.dump_pool_->enqueueTaskWithFd(
1671 DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
1672 dump_checkins = ds.dump_pool_->enqueueTaskWithFd(DUMP_CHECKINS_TASK, &DumpCheckins, _1);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001673 }
1674
Nandana Dutt5c390032019-03-12 10:52:56 +00001675 // Dump various things. Note that anything that takes "long" (i.e. several seconds) should
1676 // check intermittently (if it's intrerruptable like a foreach on pids) and/or should be wrapped
1677 // in a consent check (via RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK).
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001678 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001679 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001680 DumpBlockStatFiles();
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001681 DumpFile("MEMORY INFO", "/proc/meminfo");
1682 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001683 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001684
Kevin Jeon947922b2022-09-21 00:29:18 +00001685 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "BUGREPORT_PROCDUMP", {"bugreport_procdump"},
1686 CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001687
Sunny Goyal35949782019-11-19 15:54:36 -08001688 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpVisibleWindowViews);
1689
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001690 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1691 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1692 DumpFile("SLAB INFO", "/proc/slabinfo");
1693 DumpFile("ZONEINFO", "/proc/zoneinfo");
1694 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1695 DumpFile("BUDDYINFO", "/proc/buddyinfo");
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001696 DumpExternalFragmentationInfo();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001697
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001698 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001699
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001700 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001701 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001702
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001703 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001704 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_hals));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001705 } else {
1706 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_HALS_TASK, DumpHals);
1707 }
Steven Moreland81b429e2017-01-31 19:50:46 -08001708
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001709 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001710 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001711 struct stat s;
1712 if (stat("/proc/modules", &s) != 0) {
1713 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1714 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001715 RunCommand("LSMOD", {"lsmod"});
Woody Linc198f252021-05-04 16:37:11 +08001716 RunCommand("MODULES INFO",
1717 {"sh", "-c", "cat /proc/modules | cut -d' ' -f1 | "
1718 " while read MOD ; do echo modinfo:$MOD ; modinfo $MOD ; "
1719 "done"}, CommandOptions::AS_ROOT);
Felipe Lemee4eca582016-06-10 17:48:08 -07001720 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001721
Tom Cherryb87dbfa2020-07-28 11:28:53 -07001722 if (android::base::GetBoolProperty("ro.logd.kernel", false)) {
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001723 DoKernelLogcat();
1724 } else {
1725 do_dmesg();
1726 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001727
Devin Moore8df81bb2022-06-08 22:47:02 +00001728 DumpVintf();
1729
Felipe Lemef0292972016-11-22 13:57:05 -08001730 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001731
Jeff Brown1dc94e32014-09-11 14:15:27 -07001732 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001733 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001734
Jack Yu5a6b2e22020-08-14 18:13:35 +08001735 /* Dump Nfc NCI logs */
1736 ds.AddDir("/data/misc/nfc/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001737
Paul Chang0d2aad72020-02-13 20:04:03 +08001738 if (ds.options_->do_screenshot && !ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001739 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001740 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001741 }
1742
Felipe Lemee184f662016-10-27 10:04:47 -07001743 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001744
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001745 MaybeAddSystemTraceToZip();
1746
Narayan Kamath8f788292017-05-25 13:20:39 +01001747 // NOTE: tombstones are always added as separate entries in the zip archive
1748 // and are not interspersed with the main report.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001749 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
Narayan Kamathbd863722017-06-01 18:50:12 +01001750 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001751 if (!tombstones_dumped) {
1752 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001753 }
1754
Jayachandran Ca94c7172017-06-10 15:08:12 -07001755 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001756
Lorenzo Colitti807f2dd2022-05-27 12:48:37 +09001757 RunDumpsys("EBPF MAP STATS", {"connectivity", "trafficcontroller"});
Chenbo Feng276a3b62018-08-07 11:44:49 -07001758
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001759 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001760
Woody Lin20767a92022-11-29 15:50:24 +08001761 DumpShutdownCheckpoints();
1762
Jayachandran Ca94c7172017-06-10 15:08:12 -07001763 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001764
1765 dump_route_tables();
1766
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001767 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1768 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1769 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001770
Nandana Dutt5c390032019-03-12 10:52:56 +00001771 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysHigh);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001772
Chiachang Wang668ede42021-05-17 17:14:20 +08001773 // The dump mechanism in connectivity is refactored due to modularization work. Connectivity can
1774 // only register with a default priority(NORMAL priority). Dumpstate has to call connectivity
1775 // dump with priority parameters to dump high priority information.
1776 RunDumpsys("SERVICE HIGH connectivity", {"connectivity", "--dump-priority", "HIGH"},
1777 CommandOptions::WithTimeout(10).Build());
1778
Elliott Hughes23ccc622017-02-28 10:14:22 -08001779 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001780
Joe Onoratod38bc3a2023-06-29 15:48:28 -07001781 DumpFile("SYSTEM BUILD-TIME RELEASE FLAGS", "/system/etc/build_flags.json");
1782 DumpFile("SYSTEM_EXT BUILD-TIME RELEASE FLAGS", "/system_ext/etc/build_flags.json");
1783 DumpFile("PRODUCT BUILD-TIME RELEASE FLAGS", "/product/etc/build_flags.json");
1784 DumpFile("VENDOR BUILD-TIME RELEASE FLAGS", "/vendor/etc/build_flags.json");
1785
MÃ¥rten Kongstad5ad813f2023-09-28 10:09:18 +02001786 RunCommand("ACONFIG FLAGS", {PRINT_FLAGS},
1787 CommandOptions::WithTimeout(10).Always().DropRoot().Build());
Joe Onoratod38bc3a2023-06-29 15:48:28 -07001788
Jin Qianf334d662017-10-10 14:41:37 -07001789 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001790
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001791 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001792
Colin Crossf45fa6b2012-03-26 12:38:26 -07001793 /* Binder state is expensive to look at as it uses a lot of memory. */
Hridya Valsaraju920ba712020-02-09 16:27:01 -08001794 std::string binder_logs_dir = access("/dev/binderfs/binder_logs", R_OK) ?
1795 "/sys/kernel/debug/binder" : "/dev/binderfs/binder_logs";
1796
1797 DumpFile("BINDER FAILED TRANSACTION LOG", binder_logs_dir + "/failed_transaction_log");
1798 DumpFile("BINDER TRANSACTION LOG", binder_logs_dir + "/transaction_log");
1799 DumpFile("BINDER TRANSACTIONS", binder_logs_dir + "/transactions");
1800 DumpFile("BINDER STATS", binder_logs_dir + "/stats");
1801 DumpFile("BINDER STATE", binder_logs_dir + "/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001802
Yifan Hongd90cc652020-02-08 16:52:02 -08001803 ds.AddDir(SNAPSHOTCTL_LOG_DIR, false);
1804
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001805 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001806 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_board));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001807 } else {
1808 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
1809 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001810
Steven Moreland7440ddb2016-12-15 16:13:39 -08001811 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001812 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1813 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001814 // su does not exist on user builds, so try running without it.
1815 // This way any implementations of vril-dump that do not require
1816 // root can run on user builds.
1817 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001818 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001819 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001820 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001821 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001822 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001823 }
1824
Felipe Lemed8b94e52016-12-08 10:21:44 -08001825 printf("========================================================\n");
1826 printf("== Android Framework Services\n");
1827 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001828
Nandana Dutt5c390032019-03-12 10:52:56 +00001829 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001830
Jack He91ff2fe2021-02-18 18:23:43 -08001831 /* Dump Bluetooth HCI logs after getting bluetooth_manager dumpsys */
1832 ds.AddDir("/data/misc/bluetooth/logs", true);
1833
Rhed Jaoe017f982020-07-21 17:58:41 +08001834 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001835 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_checkins));
Rhed Jaoe017f982020-07-21 17:58:41 +08001836 } else {
1837 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_CHECKINS_TASK, DumpCheckins);
1838 }
Dianne Hackborn02bea972013-06-26 18:59:09 -07001839
Rhed Jaoc5f7ec32020-12-22 22:11:08 +08001840 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpAppInfos);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001841
Adrian Roos8b397ab2017-04-04 16:35:44 -07001842 printf("========================================================\n");
1843 printf("== Dropbox crashes\n");
1844 printf("========================================================\n");
1845
1846 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1847 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1848
Felipe Lemed8b94e52016-12-08 10:21:44 -08001849 printf("========================================================\n");
1850 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1851 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1852 printf("========================================================\n");
1853 printf("== dumpstate: done (id %d)\n", ds.id_);
1854 printf("========================================================\n");
Bookatz38472142018-09-28 10:20:24 -07001855
1856 printf("========================================================\n");
1857 printf("== Obtaining statsd metadata\n");
1858 printf("========================================================\n");
1859 // This differs from the usual dumpsys stats, which is the stats report data.
1860 RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
Mike Ma5c267872019-08-21 11:31:34 -07001861
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +09001862 // Add linker configuration directory
1863 ds.AddDir(LINKERCONFIG_DIR, true);
1864
Li Li830179f2022-01-04 12:53:29 -08001865 /* Dump frozen cgroupfs */
1866 dump_frozen_cgroupfs();
Li Li2eedd412021-06-30 15:11:53 -07001867
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001868 if (ds.dump_pool_) {
Aaron Huang24d215d2022-04-27 18:51:16 +08001869 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_netstats_report));
1870 } else {
1871 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_NETSTATS_PROTO_TASK,
1872 DumpNetstatsProto);
1873 }
1874
1875 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001876 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_incident_report));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001877 } else {
1878 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_INCIDENT_REPORT_TASK,
1879 DumpIncidentReport);
1880 }
Mike Ma5c267872019-08-21 11:31:34 -07001881
Kean Mariotti306633e2022-09-05 16:30:47 +00001882 MaybeAddUiTracesToZip();
1883
Nandana Dutt5c390032019-03-12 10:52:56 +00001884 return Dumpstate::RunStatus::OK;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001885}
1886
Nandana Dutt5c390032019-03-12 10:52:56 +00001887/*
1888 * Dumps state for the default case; drops root after it's no longer necessary.
1889 *
1890 * Returns RunStatus::OK if everything went fine.
1891 * Returns RunStatus::ERROR if there was an error.
1892 * Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport
1893 * with the caller.
1894 */
Jichao Lie89d9c12019-11-21 19:02:51 -08001895Dumpstate::RunStatus Dumpstate::DumpstateDefaultAfterCritical() {
Nandana Duttdb379fa2019-10-09 16:54:41 +01001896 // Capture first logcat early on; useful to take a snapshot before dumpstate logs take over the
1897 // buffer.
1898 DoLogcat();
1899 // Capture timestamp after first logcat to use in next logcat
1900 time_t logcat_ts = time(nullptr);
1901
Nandana Dutt4be45d12018-09-26 15:04:23 +01001902 /* collect stack traces from Dalvik and native processes (needs root) */
Chris Morinbc223142022-02-04 14:17:11 -08001903 std::future<std::string> dump_traces;
Rhed Jao5377d792020-07-16 17:37:39 +08001904 if (dump_pool_) {
1905 RETURN_IF_USER_DENIED_CONSENT();
1906 // One thread is enough since we only need to enqueue DumpTraces here.
1907 dump_pool_->start(/* thread_counts = */1);
1908
1909 // DumpTraces takes long time, post it to the another thread in the
1910 // pool, if pool is available
Chris Morinbc223142022-02-04 14:17:11 -08001911 dump_traces = dump_pool_->enqueueTask(
1912 DUMP_TRACES_TASK, &Dumpstate::DumpTraces, &ds, &dump_traces_path);
Rhed Jao5377d792020-07-16 17:37:39 +08001913 } else {
1914 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_TRACES_TASK, ds.DumpTraces,
1915 &dump_traces_path);
1916 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001917
1918 /* Run some operations that require root. */
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001919 if (!PropertiesHelper::IsDryRun()) {
Chris Morinc2cba7a2022-02-01 17:06:50 -08001920 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX);
1921 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX);
Andy Hungd62f7e62024-01-11 15:47:52 -08001922 ds.anr_trace_data_ = GetDumpFds(ANR_DIR, ANR_TRACE_FILE_PREFIX);
Woody Lin20767a92022-11-29 15:50:24 +08001923 ds.shutdown_checkpoints_ = GetDumpFds(
1924 SHUTDOWN_CHECKPOINTS_DIR, SHUTDOWN_CHECKPOINTS_FILE_PREFIX);
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001925 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001926
1927 ds.AddDir(RECOVERY_DIR, true);
1928 ds.AddDir(RECOVERY_DATA_DIR, true);
1929 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
Kelvin Zhang6eaa0f92022-09-12 09:29:19 -07001930 ds.AddDir(UPDATE_ENGINE_PREF_DIR, true);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001931 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1932 if (!PropertiesHelper::IsUserBuild()) {
1933 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1934 ds.AddDir(PROFILE_DATA_DIR_REF, true);
Calin Juravlef84d3692020-04-28 15:31:12 -07001935 ds.AddZipEntry(ZIP_ROOT_DIR + PACKAGE_DEX_USE_LIST, PACKAGE_DEX_USE_LIST);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001936 }
Jerry Changa1df8a92020-01-02 16:03:39 +08001937 ds.AddDir(PREREBOOT_DATA_DIR, false);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001938 add_mountinfo();
Peter Collingbourne78aa2942023-02-15 14:50:31 -08001939 for (const char* path : {"/proc/cpuinfo", "/proc/meminfo"}) {
1940 ds.AddZipEntry(ZIP_ROOT_DIR + path, path);
1941 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001942 DumpIpTablesAsRoot();
David Andersond9ba4752018-12-11 18:26:59 -08001943 DumpDynamicPartitionInfo();
Yifan Hong3945e1b2019-10-29 12:59:23 -07001944 ds.AddDir(OTA_METADATA_DIR, true);
Jeff Sharkey9df29d52023-02-06 14:26:30 -07001945 if (!PropertiesHelper::IsUserBuild()) {
1946 // Include dropbox entry files inside ZIP, but exclude
1947 // noisy WTF and StrictMode entries
1948 dump_files("", DROPBOX_DIR, skip_wtf_strictmode, _add_file_from_fd);
1949 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001950
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001951 // Capture any IPSec policies in play. No keys are exposed here.
Nandana Dutt4be45d12018-09-26 15:04:23 +01001952 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1953
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001954 // Dump IPsec stats. No keys are exposed here.
1955 DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
1956
Nandana Dutt4be45d12018-09-26 15:04:23 +01001957 // Run ss as root so we can see socket marks.
1958 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1959
1960 // Run iotop as root to show top 100 IO threads
1961 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1962
Erick Reyese68df822019-02-11 14:46:36 -08001963 // Gather shared memory buffer info if the product implements it
Hridya Valsaraju1da80c52021-01-09 22:10:11 -08001964 RunCommand("Dmabuf dump", {"dmabuf_dump"});
1965 RunCommand("Dmabuf per-buffer/per-exporter/per-device stats", {"dmabuf_dump", "-b"});
Erick Reyese68df822019-02-11 14:46:36 -08001966
Minchan Kim22c6a1e2019-09-30 15:58:10 -07001967 DumpFile("PSI cpu", "/proc/pressure/cpu");
1968 DumpFile("PSI memory", "/proc/pressure/memory");
1969 DumpFile("PSI io", "/proc/pressure/io");
1970
Steven Moreland9379c462023-12-21 02:04:27 +00001971 ds.AddZipEntry(ZIP_ROOT_DIR + KERNEL_CONFIG, KERNEL_CONFIG);
1972
MÃ¥rten Kongstad60195a72022-09-20 14:14:20 +02001973 RunCommand("SDK EXTENSIONS", {SDK_EXT_INFO, "--dump"},
1974 CommandOptions::WithTimeout(10).Always().DropRoot().Build());
1975
Nattharat Jariyanuntanaetb250cae2024-05-15 07:48:19 +00001976 // Dump UWB UCI logs here because apexdata requires root access
1977 ds.AddDir(UWB_LOG_DIR, true);
1978
Rhed Jao5377d792020-07-16 17:37:39 +08001979 if (dump_pool_) {
1980 RETURN_IF_USER_DENIED_CONSENT();
Chris Morinbc223142022-02-04 14:17:11 -08001981 WaitForTask(std::move(dump_traces));
Rhed Jao5377d792020-07-16 17:37:39 +08001982
Chris Morinbc223142022-02-04 14:17:11 -08001983 // Current running thread in the pool is the root user also. Delete
1984 // the pool and make a new one later to ensure none of threads in the pool are root.
1985 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao5377d792020-07-16 17:37:39 +08001986 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001987 if (!DropRootUser()) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001988 return Dumpstate::RunStatus::ERROR;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001989 }
1990
Nandana Dutt5c390032019-03-12 10:52:56 +00001991 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttdb379fa2019-10-09 16:54:41 +01001992 Dumpstate::RunStatus status = dumpstate();
1993 // Capture logcat since the last time we did it.
1994 DoSystemLogcat(logcat_ts);
1995 return status;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001996}
1997
Rhed Jaob5685b32020-08-14 17:19:17 +08001998// Common states for telephony and wifi which are needed to be collected before
1999// dumpstate drop the root user.
2000static void DumpstateRadioAsRoot() {
2001 DumpIpTablesAsRoot();
2002 ds.AddDir(LOGPERSIST_DATA_DIR, false);
2003}
2004
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002005// This method collects common dumpsys for telephony and wifi. Typically, wifi
2006// reports are fine to include all information, but telephony reports on user
2007// builds need to strip some content (see DumpstateTelephonyOnly).
2008static void DumpstateRadioCommon(bool include_sensitive_info = true) {
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002009 // We need to be picky about some stuff for telephony reports on user builds.
2010 if (!include_sensitive_info) {
2011 // Only dump the radio log buffer (other buffers and dumps contain too much unrelated info).
2012 DoRadioLogcat();
2013 } else {
Rhed Jaob5685b32020-08-14 17:19:17 +08002014 // DumpHals takes long time, post it to the another thread in the pool,
2015 // if pool is available.
Chris Morinbc223142022-02-04 14:17:11 -08002016 std::future<std::string> dump_hals;
Rhed Jaob5685b32020-08-14 17:19:17 +08002017 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002018 dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
Rhed Jaob5685b32020-08-14 17:19:17 +08002019 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002020 // Contains various system properties and process startup info.
2021 do_dmesg();
2022 // Logs other than the radio buffer may contain package/component names and potential PII.
2023 DoLogcat();
2024 // Too broad for connectivity problems.
2025 DoKmsg();
Rhed Jaob5685b32020-08-14 17:19:17 +08002026 // DumpHals contains unrelated hardware info (camera, NFC, biometrics, ...).
2027 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002028 WaitForTask(std::move(dump_hals));
Rhed Jaob5685b32020-08-14 17:19:17 +08002029 } else {
2030 RUN_SLOW_FUNCTION_AND_LOG(DUMP_HALS_TASK, DumpHals);
2031 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002032 }
2033
Jayachandran Ca94c7172017-06-10 15:08:12 -07002034 DumpPacketStats();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002035 DumpIpAddrAndRules();
2036 dump_route_tables();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002037 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
2038 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08002039}
2040
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002041// We use "telephony" here for legacy reasons, though this now really means "connectivity" (cellular
2042// + wifi + networking). This method collects dumpsys for connectivity debugging only. General rules
2043// for what can be included on user builds: all reported information MUST directly relate to
2044// connectivity debugging or customer support and MUST NOT contain unrelated personally identifiable
2045// information. This information MUST NOT identify user-installed packages (UIDs are OK, package
2046// names are not), and MUST NOT contain logs of user application traffic.
2047// TODO(b/148168577) rename this and other related fields/methods to "connectivity" instead.
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08002048static void DumpstateTelephonyOnly(const std::string& calling_package) {
mukesh agrawal253dad42018-01-23 21:59:59 -08002049 DurationReporter duration_reporter("DUMPSTATE");
Jichao Lie89d9c12019-11-21 19:02:51 -08002050
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002051 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
mukesh agrawal253dad42018-01-23 21:59:59 -08002052
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002053 const bool include_sensitive_info = !PropertiesHelper::IsUserBuild();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002054
Rhed Jaob5685b32020-08-14 17:19:17 +08002055 DumpstateRadioAsRoot();
2056 if (!DropRootUser()) {
2057 return;
2058 }
2059
2060 // Starts thread pool after the root user is dropped, and two additional threads
2061 // are created for DumpHals in the DumpstateRadioCommon and DumpstateBoard.
Chris Morinbc223142022-02-04 14:17:11 -08002062 std::future<std::string> dump_board;
Rhed Jaob5685b32020-08-14 17:19:17 +08002063 if (ds.dump_pool_) {
2064 ds.dump_pool_->start(/*thread_counts =*/2);
2065
2066 // DumpstateBoard takes long time, post it to the another thread in the pool,
2067 // if pool is available.
Chris Morinbc223142022-02-04 14:17:11 -08002068 dump_board = ds.dump_pool_->enqueueTaskWithFd(
2069 DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
Rhed Jaob5685b32020-08-14 17:19:17 +08002070 }
2071
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002072 DumpstateRadioCommon(include_sensitive_info);
2073
2074 if (include_sensitive_info) {
2075 // Contains too much unrelated PII, and given the unstructured nature of sysprops, we can't
2076 // really cherrypick all of the connectivity-related ones. Apps generally have no business
2077 // reading these anyway, and there should be APIs to supply the info in a more app-friendly
2078 // way.
2079 RunCommand("SYSTEM PROPERTIES", {"getprop"});
2080 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002081
2082 printf("========================================================\n");
2083 printf("== Android Framework Services\n");
2084 printf("========================================================\n");
2085
Vishnu Nair652cc802017-11-30 15:18:30 -08002086 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2087 SEC_TO_MSEC(10));
Hunter Knepshield31cbae12021-05-11 16:23:24 -07002088 RunDumpsys("DUMPSYS", {"vcn_management"}, CommandOptions::WithTimeout(90).Build(),
2089 SEC_TO_MSEC(10));
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08002090 if (include_sensitive_info) {
2091 // Carrier apps' services will be dumped below in dumpsys activity service all-non-platform.
2092 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
2093 SEC_TO_MSEC(10));
2094 } else {
2095 // If the caller is a carrier app and has a carrier service, dump it here since we aren't
2096 // running dumpsys activity service all-non-platform below. Due to the increased output, we
2097 // give a higher timeout as well.
2098 RunDumpsys("DUMPSYS", {"carrier_config", "--requesting-package", calling_package},
2099 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(30));
2100 }
2101 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002102 RunDumpsys("DUMPSYS", {"netpolicy"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2103 RunDumpsys("DUMPSYS", {"network_management"}, CommandOptions::WithTimeout(90).Build(),
Sooraj Sasindrane8d98912018-04-20 11:31:55 -07002104 SEC_TO_MSEC(10));
Hunter Knepshield0fe51b12020-03-05 16:58:20 -08002105 RunDumpsys("DUMPSYS", {"telephony.registry"}, CommandOptions::WithTimeout(90).Build(),
2106 SEC_TO_MSEC(10));
Jack Yu773cc032023-03-16 22:43:39 -07002107 RunDumpsys("DUMPSYS", {"isub"}, CommandOptions::WithTimeout(90).Build(),
2108 SEC_TO_MSEC(10));
Grant Menke56698972023-02-24 13:11:07 -08002109 RunDumpsys("DUMPSYS", {"telecom"}, CommandOptions::WithTimeout(90).Build(),
2110 SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002111 if (include_sensitive_info) {
2112 // Contains raw IP addresses, omit from reports on user builds.
2113 RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2114 // Contains raw destination IP/MAC addresses, omit from reports on user builds.
2115 RunDumpsys("DUMPSYS", {"connmetrics"}, CommandOptions::WithTimeout(90).Build(),
2116 SEC_TO_MSEC(10));
2117 // Contains package/component names, omit from reports on user builds.
2118 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
2119 SEC_TO_MSEC(10));
2120 // Contains package names, but should be relatively simple to remove them (also contains
2121 // UIDs already), omit from reports on user builds.
2122 RunDumpsys("BATTERYSTATS", {"deviceidle"}, CommandOptions::WithTimeout(90).Build(),
2123 SEC_TO_MSEC(10));
2124 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002125
2126 printf("========================================================\n");
2127 printf("== Running Application Services\n");
2128 printf("========================================================\n");
2129
2130 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
2131
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002132 if (include_sensitive_info) {
2133 printf("========================================================\n");
2134 printf("== Running Application Services (non-platform)\n");
2135 printf("========================================================\n");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002136
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002137 // Contains package/component names and potential PII, omit from reports on user builds.
2138 // To get dumps of the active CarrierService(s) on user builds, we supply an argument to the
2139 // carrier_config dumpsys instead.
2140 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
2141 DUMPSYS_COMPONENTS_OPTIONS);
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002142
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002143 printf("========================================================\n");
2144 printf("== Checkins\n");
2145 printf("========================================================\n");
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002146
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002147 // Contains package/component names, omit from reports on user builds.
2148 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
2149 }
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002150
2151 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07002152 printf("== dumpstate: done (id %d)\n", ds.id_);
2153 printf("========================================================\n");
Rhed Jaob5685b32020-08-14 17:19:17 +08002154
2155 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002156 WaitForTask(std::move(dump_board));
Rhed Jaob5685b32020-08-14 17:19:17 +08002157 } else {
2158 RUN_SLOW_FUNCTION_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
2159 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002160}
2161
mukesh agrawal253dad42018-01-23 21:59:59 -08002162// This method collects dumpsys for wifi debugging only
2163static void DumpstateWifiOnly() {
2164 DurationReporter duration_reporter("DUMPSTATE");
2165
Rhed Jaob5685b32020-08-14 17:19:17 +08002166 DumpstateRadioAsRoot();
2167 if (!DropRootUser()) {
2168 return;
2169 }
2170
2171 // Starts thread pool after the root user is dropped. Only one additional
2172 // thread is needed for DumpHals in the DumpstateRadioCommon.
2173 if (ds.dump_pool_) {
2174 ds.dump_pool_->start(/*thread_counts =*/1);
2175 }
2176
mukesh agrawal253dad42018-01-23 21:59:59 -08002177 DumpstateRadioCommon();
2178
2179 printf("========================================================\n");
2180 printf("== Android Framework Services\n");
2181 printf("========================================================\n");
2182
2183 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2184 SEC_TO_MSEC(10));
2185 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
2186 SEC_TO_MSEC(10));
2187
2188 printf("========================================================\n");
2189 printf("== dumpstate: done (id %d)\n", ds.id_);
2190 printf("========================================================\n");
2191}
2192
Elis Elliott8e401ad2023-08-08 11:18:59 +00002193// Collects a lightweight dumpstate to be used for debugging onboarding related flows.
2194static void DumpstateOnboardingOnly() {
2195 ds.AddDir(LOGPERSIST_DATA_DIR, false);
2196}
2197
Christopher Ferris83e0e842024-05-31 13:13:34 -07002198static std::string GetTimestamp(const timespec& ts) {
2199 tm tm;
2200 localtime_r(&ts.tv_sec, &tm);
2201
2202 // Reserve enough space for the entire time string, includes the space
2203 // for the '\0' to make the calculations below easier by using size for
2204 // the total string size.
2205 std::string str(sizeof("1970-01-01 00:00:00.123456789+0830"), '\0');
2206 size_t n = strftime(str.data(), str.size(), "%F %H:%M", &tm);
2207 if (n == 0) {
2208 return "TIMESTAMP FAILURE";
2209 }
2210 int num_chars = snprintf(&str[n], str.size() - n, ":%02d.%09ld", tm.tm_sec, ts.tv_nsec);
2211 if (num_chars > str.size() - n) {
2212 return "TIMESTAMP FAILURE";
2213 }
2214 n += static_cast<size_t>(num_chars);
2215 if (strftime(&str[n], str.size() - n, "%z", &tm) == 0) {
2216 return "TIMESTAMP FAILURE";
2217 }
2218 return str;
2219}
2220
2221static std::string GetCmdline(pid_t pid) {
2222 std::string cmdline;
2223 if (!android::base::ReadFileToString(android::base::StringPrintf("/proc/%d/cmdline", pid),
2224 &cmdline)) {
2225 return "UNKNOWN";
2226 }
2227 // There are '\0' terminators between arguments, convert them to spaces.
2228 // But start by skipping all trailing '\0' values.
2229 size_t cur = cmdline.size() - 1;
2230 while (cur != 0 && cmdline[cur] == '\0') {
2231 cur--;
2232 }
2233 if (cur == 0) {
2234 return "UNKNOWN";
2235 }
2236 while ((cur = cmdline.rfind('\0', cur)) != std::string::npos) {
2237 cmdline[cur] = ' ';
2238 }
2239 return cmdline;
2240}
2241
2242static void DumpPidHeader(int fd, pid_t pid, const timespec& ts) {
2243 // For consistency, the header to this message matches the one
2244 // dumped by debuggerd.
2245 dprintf(fd, "\n----- pid %d at %s -----\n", pid, GetTimestamp(ts).c_str());
2246 dprintf(fd, "Cmd line: %s\n", GetCmdline(pid).c_str());
2247}
2248
2249static void DumpPidFooter(int fd, pid_t pid) {
2250 // For consistency, the footer to this message matches the one
2251 // dumped by debuggerd.
2252 dprintf(fd, "----- end %d -----\n", pid);
2253}
2254
2255static bool DumpBacktrace(int fd, pid_t pid, bool is_java_process) {
2256 int ret = dump_backtrace_to_file_timeout(
2257 pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace, 3, fd);
2258 if (ret == -1 && is_java_process) {
2259 // Tried to unwind as a java process, try a native unwind.
2260 dprintf(fd, "Java unwind failed for pid %d, trying a native unwind.\n", pid);
2261 ret = dump_backtrace_to_file_timeout(pid, kDebuggerdNativeBacktrace, 3, fd);
2262 }
2263 return ret != -1;
2264}
2265
Nandana Duttcf419a72019-03-14 10:40:17 +00002266Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
Gavin Corkery789d7a52021-02-24 23:52:35 +00002267 const std::string temp_file_pattern = ds.bugreport_internal_dir_ + "/dumptrace_XXXXXX";
Nandana Duttfaafd522019-03-11 09:23:09 +00002268 const size_t buf_size = temp_file_pattern.length() + 1;
2269 std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
2270 memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
2271
2272 // Create a new, empty file to receive all trace dumps.
2273 //
2274 // TODO: This can be simplified once we remove support for the old style
2275 // dumps. We can have a file descriptor passed in to dump_traces instead
2276 // of creating a file, closing it and then reopening it again.
2277 android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
2278 if (fd < 0) {
2279 MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002280 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002281 }
2282
2283 // Nobody should have access to this temporary file except dumpstate, but we
2284 // temporarily grant 'read' to 'others' here because this file is created
2285 // when tombstoned is still running as root, but dumped after dropping. This
2286 // can go away once support for old style dumping has.
2287 const int chmod_ret = fchmod(fd, 0666);
2288 if (chmod_ret < 0) {
2289 MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002290 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002291 }
2292
2293 std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
2294 if (proc.get() == nullptr) {
2295 MYLOGE("opendir /proc failed: %s\n", strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002296 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002297 }
2298
2299 // Number of times process dumping has timed out. If we encounter too many
2300 // failures, we'll give up.
2301 int timeout_failures = 0;
2302 bool dalvik_found = false;
2303
Jayant Chowdharya0a8eb22022-05-20 03:30:09 +00002304 const std::set<int> hal_pids = get_interesting_pids();
Nandana Duttfaafd522019-03-11 09:23:09 +00002305
2306 struct dirent* d;
2307 while ((d = readdir(proc.get()))) {
Nandana Duttcf419a72019-03-14 10:40:17 +00002308 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttfaafd522019-03-11 09:23:09 +00002309 int pid = atoi(d->d_name);
2310 if (pid <= 0) {
2311 continue;
2312 }
2313
2314 const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
2315 std::string exe;
2316 if (!android::base::Readlink(link_name, &exe)) {
2317 continue;
2318 }
2319
2320 bool is_java_process;
2321 if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
2322 // Don't bother dumping backtraces for the zygote.
2323 if (IsZygote(pid)) {
2324 continue;
2325 }
2326
2327 dalvik_found = true;
2328 is_java_process = true;
2329 } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
2330 is_java_process = false;
2331 } else {
2332 // Probably a native process we don't care about, continue.
2333 continue;
2334 }
2335
2336 // If 3 backtrace dumps fail in a row, consider debuggerd dead.
2337 if (timeout_failures == 3) {
2338 dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
2339 break;
2340 }
2341
Christopher Ferris83e0e842024-05-31 13:13:34 -07002342 timespec start_timespec;
2343 clock_gettime(CLOCK_REALTIME, &start_timespec);
2344 if (IsCached(pid)) {
2345 DumpPidHeader(fd, pid, start_timespec);
2346 dprintf(fd, "Process is cached, skipping backtrace due to high chance of timeout.\n");
2347 DumpPidFooter(fd, pid);
2348 continue;
2349 }
Nandana Duttfaafd522019-03-11 09:23:09 +00002350
Christopher Ferris83e0e842024-05-31 13:13:34 -07002351 const uint64_t start = Nanotime();
2352 if (!DumpBacktrace(fd, pid, is_java_process)) {
2353 if (IsCached(pid)) {
2354 DumpPidHeader(fd, pid, start_timespec);
2355 dprintf(fd, "Backtrace failed, but process has become cached.\n");
2356 DumpPidFooter(fd, pid);
2357 continue;
2358 }
2359
2360 DumpPidHeader(fd, pid, start_timespec);
2361 dprintf(fd, "Backtrace gathering failed, likely due to a timeout.\n");
2362 DumpPidFooter(fd, pid);
2363
2364 dprintf(fd, "\n[dump %s stack %d: %.3fs elapsed]\n",
2365 is_java_process ? "dalvik" : "native", pid,
2366 (float)(Nanotime() - start) / NANOS_PER_SEC);
Nandana Duttfaafd522019-03-11 09:23:09 +00002367 timeout_failures++;
2368 continue;
2369 }
2370
2371 // We've successfully dumped stack traces, reset the failure count
2372 // and write a summary of the elapsed time to the file and continue with the
2373 // next process.
2374 timeout_failures = 0;
2375
2376 dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
2377 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
2378 }
2379
2380 if (!dalvik_found) {
2381 MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
2382 }
2383
Nandana Duttcf419a72019-03-14 10:40:17 +00002384 *path = file_name_buf.release();
2385 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002386}
2387
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002388static dumpstate_hal_hidl::DumpstateMode GetDumpstateHalModeHidl(
2389 const Dumpstate::BugreportMode bugreport_mode) {
2390 switch (bugreport_mode) {
2391 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2392 return dumpstate_hal_hidl::DumpstateMode::FULL;
2393 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2394 return dumpstate_hal_hidl::DumpstateMode::INTERACTIVE;
2395 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2396 return dumpstate_hal_hidl::DumpstateMode::REMOTE;
2397 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2398 return dumpstate_hal_hidl::DumpstateMode::WEAR;
2399 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2400 return dumpstate_hal_hidl::DumpstateMode::CONNECTIVITY;
2401 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2402 return dumpstate_hal_hidl::DumpstateMode::WIFI;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002403 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002404 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2405 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2406 }
2407 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2408}
2409
2410static dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode GetDumpstateHalModeAidl(
2411 const Dumpstate::BugreportMode bugreport_mode) {
2412 switch (bugreport_mode) {
2413 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2414 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::FULL;
2415 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2416 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::INTERACTIVE;
2417 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2418 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::REMOTE;
2419 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2420 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WEAR;
2421 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2422 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::CONNECTIVITY;
2423 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2424 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WIFI;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002425 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002426 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2427 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2428 }
2429 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2430}
2431
2432static void DoDumpstateBoardHidl(
2433 const sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_1_0,
2434 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2435 const Dumpstate::BugreportMode bugreport_mode,
2436 const size_t timeout_sec) {
2437
2438 using ScopedNativeHandle =
2439 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
2440 ScopedNativeHandle handle(native_handle_create(static_cast<int>(dumpstate_fds.size()), 0),
2441 [](native_handle_t* handle) {
2442 // we don't close file handle's here
2443 // via native_handle_close(handle)
2444 // instead we let dumpstate_fds close the file handles when
2445 // dumpstate_fds gets destroyed
2446 native_handle_delete(handle);
2447 });
2448 if (handle == nullptr) {
2449 MYLOGE("Could not create native_handle for dumpstate HAL\n");
2450 return;
2451 }
2452
2453 for (size_t i = 0; i < dumpstate_fds.size(); i++) {
2454 handle.get()->data[i] = dumpstate_fds[i].get();
2455 }
2456
2457 // Prefer version 1.1 if available. New devices launching with R are no longer allowed to
2458 // implement just 1.0.
2459 const char* descriptor_to_kill;
2460 using DumpstateBoardTask = std::packaged_task<bool()>;
2461 DumpstateBoardTask dumpstate_board_task;
2462 sp<dumpstate_hal_hidl::IDumpstateDevice> dumpstate_hal(
2463 dumpstate_hal_hidl::IDumpstateDevice::castFrom(dumpstate_hal_1_0));
2464 if (dumpstate_hal != nullptr) {
2465 MYLOGI("Using IDumpstateDevice v1.1 HIDL HAL");
2466
2467 dumpstate_hal_hidl::DumpstateMode dumpstate_hal_mode =
2468 GetDumpstateHalModeHidl(bugreport_mode);
2469
2470 descriptor_to_kill = dumpstate_hal_hidl::IDumpstateDevice::descriptor;
2471 dumpstate_board_task =
2472 DumpstateBoardTask([timeout_sec, dumpstate_hal_mode, dumpstate_hal, &handle]() -> bool {
2473 ::android::hardware::Return<dumpstate_hal_hidl::DumpstateStatus> status =
2474 dumpstate_hal->dumpstateBoard_1_1(handle.get(), dumpstate_hal_mode,
2475 SEC_TO_MSEC(timeout_sec));
2476 if (!status.isOk()) {
2477 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2478 return false;
2479 } else if (status != dumpstate_hal_hidl::DumpstateStatus::OK) {
2480 MYLOGE("dumpstateBoard failed with DumpstateStatus::%s\n",
2481 dumpstate_hal_hidl::toString(status).c_str());
2482 return false;
2483 }
2484 return true;
2485 });
2486 } else {
2487 MYLOGI("Using IDumpstateDevice v1.0 HIDL HAL");
2488
2489 descriptor_to_kill = dumpstate_hal_hidl_1_0::IDumpstateDevice::descriptor;
2490 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal_1_0, &handle]() -> bool {
2491 ::android::hardware::Return<void> status =
2492 dumpstate_hal_1_0->dumpstateBoard(handle.get());
2493 if (!status.isOk()) {
2494 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2495 return false;
2496 }
2497 return true;
2498 });
2499 }
2500 auto result = dumpstate_board_task.get_future();
2501 std::thread(std::move(dumpstate_board_task)).detach();
2502
2503 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2504 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2505 if (!android::base::SetProperty(
2506 "ctl.interface_restart",
2507 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2508 MYLOGE("Couldn't restart dumpstate HAL\n");
2509 }
2510 }
2511 // Wait some time for init to kill dumpstate vendor HAL
2512 constexpr size_t killing_timeout_sec = 10;
2513 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2514 MYLOGE(
2515 "killing dumpstateBoard timed out after %zus, continue and "
2516 "there might be racing in content\n",
2517 killing_timeout_sec);
2518 }
2519}
2520
2521static void DoDumpstateBoardAidl(
2522 const std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal,
2523 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2524 const Dumpstate::BugreportMode bugreport_mode, const size_t timeout_sec) {
2525 MYLOGI("Using IDumpstateDevice AIDL HAL");
2526
2527 const char* descriptor_to_kill;
2528 using DumpstateBoardTask = std::packaged_task<bool()>;
2529 DumpstateBoardTask dumpstate_board_task;
2530 dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode dumpstate_hal_mode =
2531 GetDumpstateHalModeAidl(bugreport_mode);
2532
2533 descriptor_to_kill = dumpstate_hal_aidl::IDumpstateDevice::descriptor;
2534 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal, &dumpstate_fds, dumpstate_hal_mode,
2535 timeout_sec]() -> bool {
2536 auto status = dumpstate_hal->dumpstateBoard(dumpstate_fds, dumpstate_hal_mode, timeout_sec);
2537
2538 if (!status.isOk()) {
2539 MYLOGE("dumpstateBoard failed: %s\n", status.getDescription().c_str());
2540 return false;
2541 }
2542 return true;
2543 });
2544 auto result = dumpstate_board_task.get_future();
2545 std::thread(std::move(dumpstate_board_task)).detach();
2546
2547 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2548 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2549 if (!android::base::SetProperty(
2550 "ctl.interface_restart",
2551 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2552 MYLOGE("Couldn't restart dumpstate HAL\n");
2553 }
2554 }
2555 // Wait some time for init to kill dumpstate vendor HAL
2556 constexpr size_t killing_timeout_sec = 10;
2557 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2558 MYLOGE(
2559 "killing dumpstateBoard timed out after %zus, continue and "
2560 "there might be racing in content\n",
2561 killing_timeout_sec);
2562 }
2563}
2564
2565static std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> GetDumpstateBoardAidlService() {
2566 const std::string aidl_instance_name =
2567 std::string(dumpstate_hal_aidl::IDumpstateDevice::descriptor) + "/default";
2568
2569 if (!AServiceManager_isDeclared(aidl_instance_name.c_str())) {
2570 return nullptr;
2571 }
2572
2573 ndk::SpAIBinder dumpstateBinder(AServiceManager_waitForService(aidl_instance_name.c_str()));
2574
2575 return dumpstate_hal_aidl::IDumpstateDevice::fromBinder(dumpstateBinder);
2576}
2577
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002578void Dumpstate::DumpstateBoard(int out_fd) {
2579 dprintf(out_fd, "========================================================\n");
2580 dprintf(out_fd, "== Board\n");
2581 dprintf(out_fd, "========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08002582
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002583 /*
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002584 * mount debugfs for non-user builds with ro.product.debugfs_restrictions.enabled
Hridya Valsaraju51101602021-04-02 14:32:46 -07002585 * set to true and unmount it after invoking dumpstateBoard_* methods.
2586 * This is to enable debug builds to not have debugfs mounted during runtime.
2587 * It will also ensure that debugfs is only accessed by the dumpstate HAL.
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002588 */
Hridya Valsaraju51101602021-04-02 14:32:46 -07002589 auto mount_debugfs =
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002590 android::base::GetBoolProperty("ro.product.debugfs_restrictions.enabled", false);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002591 if (mount_debugfs) {
2592 RunCommand("mount debugfs", {"mount", "-t", "debugfs", "debugfs", "/sys/kernel/debug"},
2593 AS_ROOT_20);
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002594 RunCommand("chmod debugfs", {"chmod", "0755", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002595 }
2596
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002597 std::vector<std::string> paths;
2598 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07002599 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002600 paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
2601 kDumpstateBoardFiles[i].c_str()));
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002602 remover.emplace_back(android::base::make_scope_guard(
2603 std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002604 }
Jie Song9fbfad02017-06-20 16:29:42 -07002605
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002606 // get dumpstate HAL AIDL implementation
2607 std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal_handle_aidl(
2608 GetDumpstateBoardAidlService());
2609 if (dumpstate_hal_handle_aidl == nullptr) {
2610 MYLOGI("No IDumpstateDevice AIDL implementation\n");
2611 }
2612
2613 // get dumpstate HAL HIDL implementation, only if AIDL HAL implementation not found
2614 sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_handle_hidl_1_0 = nullptr;
2615 if (dumpstate_hal_handle_aidl == nullptr) {
2616 dumpstate_hal_handle_hidl_1_0 = dumpstate_hal_hidl_1_0::IDumpstateDevice::getService();
2617 if (dumpstate_hal_handle_hidl_1_0 == nullptr) {
2618 MYLOGI("No IDumpstateDevice HIDL implementation\n");
2619 }
2620 }
2621
2622 // if neither HIDL nor AIDL implementation found, then return
2623 if (dumpstate_hal_handle_hidl_1_0 == nullptr && dumpstate_hal_handle_aidl == nullptr) {
2624 MYLOGE("Could not find IDumpstateDevice implementation\n");
Wei Wang587eac92018-04-05 12:17:20 -07002625 return;
2626 }
2627
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002628 // this is used to hold the file descriptors and when this variable goes out of scope
2629 // the file descriptors are closed
2630 std::vector<::ndk::ScopedFileDescriptor> dumpstate_fds;
Wei Wang587eac92018-04-05 12:17:20 -07002631
Nandana Dutt5c390032019-03-12 10:52:56 +00002632 // TODO(128270426): Check for consent in between?
Wei Wang587eac92018-04-05 12:17:20 -07002633 for (size_t i = 0; i < paths.size(); i++) {
2634 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
2635
2636 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
2637 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
2638 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
2639 if (fd < 0) {
2640 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
2641 return;
2642 }
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002643
2644 dumpstate_fds.emplace_back(fd.release());
2645 // we call fd.release() here to make sure "fd" does not get closed
2646 // after "fd" goes out of scope after this block.
2647 // "fd" will be closed when "dumpstate_fds" goes out of scope
2648 // i.e. when we exit this function
Wei Wang587eac92018-04-05 12:17:20 -07002649 }
2650
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002651 // Given that bugreport is required to diagnose failures, it's better to set an arbitrary amount
2652 // of timeout for IDumpstateDevice than to block the rest of bugreport. In the timeout case, we
2653 // will kill the HAL and grab whatever it dumped in time.
Michael Eastwood8523ea02022-03-10 16:33:08 -08002654 constexpr size_t timeout_sec = 45;
Wei Wang587eac92018-04-05 12:17:20 -07002655
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002656 if (dumpstate_hal_handle_aidl != nullptr) {
2657 DoDumpstateBoardAidl(dumpstate_hal_handle_aidl, dumpstate_fds, options_->bugreport_mode,
2658 timeout_sec);
2659 } else if (dumpstate_hal_handle_hidl_1_0 != nullptr) {
2660 // run HIDL HAL only if AIDL HAL not found
2661 DoDumpstateBoardHidl(dumpstate_hal_handle_hidl_1_0, dumpstate_fds, options_->bugreport_mode,
2662 timeout_sec);
Wei Wang587eac92018-04-05 12:17:20 -07002663 }
2664
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002665 if (mount_debugfs) {
Hridya Valsaraju51101602021-04-02 14:32:46 -07002666 auto keep_debugfs_mounted =
2667 android::base::GetProperty("persist.dbg.keep_debugfs_mounted", "");
2668 if (keep_debugfs_mounted.empty())
2669 RunCommand("unmount debugfs", {"umount", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002670 }
2671
Wei Wang587eac92018-04-05 12:17:20 -07002672 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
2673 for (size_t i = 0; i < paths.size(); i++) {
2674 struct stat s;
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002675 if (fstat(dumpstate_fds[i].get(), &s) == -1) {
2676 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(), strerror(errno));
Wei Wang587eac92018-04-05 12:17:20 -07002677 file_sizes[i] = -1;
2678 continue;
2679 }
2680 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002681 }
2682
2683 for (size_t i = 0; i < paths.size(); i++) {
2684 if (file_sizes[i] == -1) {
2685 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002686 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002687 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07002688 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002689 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002690 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002691 remover[i].Disable();
2692 EnqueueAddZipEntryAndCleanupIfNeeded(kDumpstateBoardFiles[i], paths[i]);
2693 dprintf(out_fd, "*** See %s entry ***\n", kDumpstateBoardFiles[i].c_str());
Jie Song9fbfad02017-06-20 16:29:42 -07002694 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08002695}
2696
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002697static void ShowUsage() {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002698 fprintf(stderr,
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002699 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o directory] [-p] "
2700 "[-s] [-S] [-q] [-P] [-R] [-L] [-V version]\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002701 " -h: display this help message\n"
2702 " -b: play sound file instead of vibrate, at beginning of job\n"
2703 " -e: play sound file instead of vibrate, at end of job\n"
mhasank2d75c442020-06-11 15:05:25 -07002704 " -o: write to custom directory (only in limited mode)\n"
Abhijeet Kaurbb55a3b2019-06-13 18:07:25 +01002705 " -p: capture screenshot to filename.png\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002706 " -s: write zipped file to control socket (for init)\n"
2707 " -S: write file location to control socket (for init)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002708 " -q: disable vibrate\n"
Abhijeet Kaure370d682019-10-01 16:49:30 +01002709 " -P: send broadcast when started and do progress updates\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002710 " -R: take bugreport in remote mode (shouldn't be used with -P)\n"
Nandana Dutt235864b2019-01-22 12:10:16 +00002711 " -w: start binder service and make it wait for a call to startBugreport\n"
mhasankd451a472020-05-26 18:02:39 -07002712 " -L: output limited information that is safe for submission in feedback reports\n"
Felipe Lemed071c682016-10-20 16:48:00 -07002713 " -v: prints the dumpstate header and exit\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002714}
2715
Wei Liuf87959e2016-08-26 14:51:42 -07002716static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07002717 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07002718}
2719
Felipe Leme1d486fe2016-10-14 18:06:47 -07002720bool Dumpstate::FinishZipFile() {
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002721 // Runs all enqueued adding zip entry and cleanup tasks before finishing the zip file.
2722 if (zip_entry_tasks_) {
2723 zip_entry_tasks_->run(/* do_cancel = */false);
2724 }
2725
Felipe Leme9a523ae2016-10-20 15:10:33 -07002726 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07002727 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07002728 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002729 // Final timestamp
2730 char date[80];
2731 time_t the_real_now_please_stand_up = time(nullptr);
2732 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002733 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002734 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002735
Felipe Leme9a523ae2016-10-20 15:10:33 -07002736 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002737 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08002738 return false;
2739 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07002740 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002741 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08002742 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08002743 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08002744
Felipe Leme0f3fb202016-06-10 17:10:53 -07002745 // Add log file (which contains stderr output) to zip...
2746 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002747 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07002748 MYLOGE("Failed to add dumpstate log to .zip file\n");
2749 return false;
2750 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002751 // TODO: Should truncate the existing file.
2752 // ... and re-open it for further logging.
Nandana Dutta344cb62019-02-22 15:12:35 +00002753 if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
2754 return false;
2755 }
Felipe Leme0f3fb202016-06-10 17:10:53 -07002756 fprintf(stderr, "\n");
2757
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002758 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07002759 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002760 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002761 return false;
2762 }
2763
Felipe Leme1d486fe2016-10-14 18:06:47 -07002764 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
2765 ds.zip_file.reset(nullptr);
2766
Felipe Lemee9d2c542016-11-15 11:48:26 -08002767 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002768 android::os::UnlinkAndLogOnError(tmp_path_);
Felipe Lemec4eee562016-04-21 15:42:55 -07002769
Felipe Leme1e9edc62015-12-21 16:02:13 -08002770 return true;
2771}
Felipe Leme6e01fa62015-11-11 19:35:14 -08002772
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00002773static void SendBroadcast(const std::string& action,
2774 const std::vector<std::string>& args,
2775 int32_t user_id) {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002776 // clang-format off
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00002777 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user",
2778 std::to_string(user_id), "--receiver-foreground",
2779 "--receiver-include-background", "-a", action};
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002780 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08002781
2782 am.insert(am.end(), args.begin(), args.end());
2783
Felipe Leme8d2410e2017-02-08 09:46:08 -08002784 RunCommand("", am,
2785 CommandOptions::WithTimeout(20)
2786 .Log("Sending broadcast: '%s'\n")
2787 .Always()
2788 .DropRoot()
2789 .RedirectStderr()
2790 .Build());
2791}
2792
Felipe Leme35b8cf12017-02-10 15:47:29 -08002793static void Vibrate(int duration_ms) {
2794 // clang-format off
Lais Andrade51156962021-02-22 19:21:35 +00002795 std::vector<std::string> args = {"cmd", "vibrator_manager", "synced", "-f", "-d", "dumpstate",
2796 "oneshot", std::to_string(duration_ms)};
2797 RunCommand("", args,
Felipe Leme35b8cf12017-02-10 15:47:29 -08002798 CommandOptions::WithTimeout(10)
2799 .Log("Vibrate: '%s'\n")
2800 .Always()
2801 .Build());
2802 // clang-format on
2803}
2804
Nandana Dutt979388e2018-11-30 16:48:55 +00002805static void MaybeResolveSymlink(std::string* path) {
2806 std::string resolved_path;
2807 if (android::base::Readlink(*path, &resolved_path)) {
2808 *path = resolved_path;
2809 }
2810}
2811
Nandana Dutt4be45d12018-09-26 15:04:23 +01002812/*
2813 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002814 * and adds the version file. Return false if zip_file could not be open to write.
Nandana Dutt4be45d12018-09-26 15:04:23 +01002815 */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002816static bool PrepareToWriteToFile() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002817 MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2818
Nandana Dutt4be45d12018-09-26 15:04:23 +01002819 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2820 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002821 ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002822 char date[80];
2823 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2824 ds.name_ = date;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002825
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002826 if (ds.options_->telephony_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002827 ds.base_name_ += "-telephony";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002828 } else if (ds.options_->wifi_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002829 ds.base_name_ += "-wifi";
2830 }
2831
Paul Chang0d2aad72020-02-13 20:04:03 +08002832 if (ds.options_->do_screenshot) {
Nandana Dutt9d17b942020-03-26 10:02:59 +00002833 ds.screenshot_path_ = ds.GetPath(ds.CalledByApi() ? "-png.tmp" : ".png");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002834 }
2835 ds.tmp_path_ = ds.GetPath(".tmp");
2836 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2837
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01002838 std::string destination = ds.CalledByApi()
Nandana Dutt54dbd672019-01-11 12:58:05 +00002839 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
Nandana Dutt9a76d202019-01-21 15:56:48 +00002840 : ds.bugreport_internal_dir_.c_str();
Nandana Dutt4be45d12018-09-26 15:04:23 +01002841 MYLOGD(
Nandana Dutt235c6672019-11-14 15:22:32 +00002842 "Bugreport dir: [%s] "
2843 "Base name: [%s] "
2844 "Suffix: [%s] "
2845 "Log path: [%s] "
2846 "Temporary path: [%s] "
2847 "Screenshot path: [%s]\n",
Nandana Dutt9a76d202019-01-21 15:56:48 +00002848 destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2849 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002850
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002851 ds.path_ = ds.GetPath(ds.CalledByApi() ? "-zip.tmp" : ".zip");
2852 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2853 create_parent_dirs(ds.path_.c_str());
2854 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2855 if (ds.zip_file == nullptr) {
2856 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2857 return false;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002858 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002859 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2860 ds.AddTextZipEntry("version.txt", ds.version_);
2861 return true;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002862}
2863
2864/*
Abhijeet Kaure370d682019-10-01 16:49:30 +01002865 * Finalizes writing to the file by zipping the tmp file to the final location,
Nandana Dutt4be45d12018-09-26 15:04:23 +01002866 * printing zipped file status, etc.
2867 */
2868static void FinalizeFile() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002869 bool do_text_file = !ds.FinishZipFile();
2870 if (do_text_file) {
2871 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002872 }
mhasank2d75c442020-06-11 15:05:25 -07002873
2874 std::string final_path = ds.path_;
2875 if (ds.options_->OutputToCustomFile()) {
mhasank3a4cfb42020-06-15 18:06:43 -07002876 final_path = ds.GetPath(ds.options_->out_dir, ".zip");
mhasank2d75c442020-06-11 15:05:25 -07002877 android::os::CopyFileToFile(ds.path_, final_path);
2878 }
2879
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002880 if (ds.options_->stream_to_socket) {
2881 android::os::CopyFileToFd(ds.path_, ds.control_socket_fd_);
2882 } else if (ds.options_->progress_updates_to_socket) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002883 if (do_text_file) {
2884 dprintf(ds.control_socket_fd_,
2885 "FAIL:could not create zip file, check %s "
2886 "for more details\n",
2887 ds.log_path_.c_str());
2888 } else {
mhasank2d75c442020-06-11 15:05:25 -07002889 dprintf(ds.control_socket_fd_, "OK:%s\n", final_path.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002890 }
2891 }
2892}
2893
Nandana Dutt4be45d12018-09-26 15:04:23 +01002894
Nandana Dutt58d72e22018-11-16 10:30:48 +00002895static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2896 switch (mode) {
2897 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2898 return "BUGREPORT_FULL";
2899 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2900 return "BUGREPORT_INTERACTIVE";
2901 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2902 return "BUGREPORT_REMOTE";
2903 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2904 return "BUGREPORT_WEAR";
2905 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2906 return "BUGREPORT_TELEPHONY";
2907 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2908 return "BUGREPORT_WIFI";
Elis Elliott8e401ad2023-08-08 11:18:59 +00002909 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
2910 return "BUGREPORT_ONBOARDING";
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002911 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2912 return "BUGREPORT_DEFAULT";
Nandana Dutt58d72e22018-11-16 10:30:48 +00002913 }
2914}
2915
Steven Leeb573eb82022-11-29 22:31:35 +08002916static bool IsConsentlessBugreportAllowed(const Dumpstate::DumpOptions& options) {
2917 // only BUGREPORT_TELEPHONY does not allow using consentless bugreport
2918 return !options.telephony_only;
2919}
2920
Paul Changf59c2b72020-03-10 02:08:55 +08002921static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options,
2922 bool is_screenshot_requested) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002923 // Modify com.android.shell.BugreportProgressService#isDefaultScreenshotRequired as well for
2924 // default system screenshots.
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002925 options->bugreport_mode = mode;
2926 options->bugreport_mode_string = ModeToString(mode);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002927 switch (mode) {
2928 case Dumpstate::BugreportMode::BUGREPORT_FULL:
Paul Changf59c2b72020-03-10 02:08:55 +08002929 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002930 break;
2931 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002932 // Currently, the dumpstate binder is only used by Shell to update progress.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002933 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002934 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002935 break;
2936 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002937 options->do_vibrate = false;
2938 options->is_remote_mode = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002939 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002940 break;
2941 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
Robert Ginda55ecebd2023-04-03 22:53:13 +00002942 options->do_vibrate = false;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002943 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002944 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002945 break;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002946 // TODO(b/148168577) rename TELEPHONY everywhere to CONNECTIVITY.
Nandana Dutt58d72e22018-11-16 10:30:48 +00002947 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002948 options->telephony_only = true;
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002949 options->do_progress_updates = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002950 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002951 break;
2952 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002953 options->wifi_only = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002954 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002955 break;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002956 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
2957 options->onboarding_only = true;
2958 options->do_screenshot = false;
2959 break;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002960 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2961 break;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002962 }
2963}
2964
Nandana Dutt58d72e22018-11-16 10:30:48 +00002965static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
Nandana Dutt235c6672019-11-14 15:22:32 +00002966 MYLOGI(
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002967 "do_vibrate: %d stream_to_socket: %d progress_updates_to_socket: %d do_screenshot: %d "
Rhed Jao25f50e02020-08-20 00:10:32 +08002968 "is_remote_mode: %d show_header_only: %d telephony_only: %d "
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002969 "wifi_only: %d do_progress_updates: %d fd: %d bugreport_mode: %s "
mhasankd451a472020-05-26 18:02:39 -07002970 "limited_only: %d args: %s\n",
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002971 options.do_vibrate, options.stream_to_socket, options.progress_updates_to_socket,
Paul Chang0d2aad72020-02-13 20:04:03 +08002972 options.do_screenshot, options.is_remote_mode, options.show_header_only,
Rhed Jao25f50e02020-08-20 00:10:32 +08002973 options.telephony_only, options.wifi_only,
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002974 options.do_progress_updates, options.bugreport_fd.get(),
2975 options.bugreport_mode_string.c_str(),
2976 options.limited_only, options.args.c_str());
Nandana Dutt58d72e22018-11-16 10:30:48 +00002977}
2978
Nandana Dutt54dbd672019-01-11 12:58:05 +00002979void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
Kean Mariotti306633e2022-09-05 16:30:47 +00002980 int bugreport_flags,
Nandana Dutt54dbd672019-01-11 12:58:05 +00002981 const android::base::unique_fd& bugreport_fd_in,
Paul Changf59c2b72020-03-10 02:08:55 +08002982 const android::base::unique_fd& screenshot_fd_in,
Kholoud Mohameddef4e432024-05-15 12:47:46 +00002983 bool is_screenshot_requested,
2984 bool skip_user_consent) {
Kean Mariotti306633e2022-09-05 16:30:47 +00002985 this->use_predumped_ui_data = bugreport_flags & BugreportFlag::BUGREPORT_USE_PREDUMPED_UI_DATA;
Gavin Corkerya44686c2022-11-23 18:16:51 +00002986 this->is_consent_deferred = bugreport_flags & BugreportFlag::BUGREPORT_FLAG_DEFER_CONSENT;
Kholoud Mohameddef4e432024-05-15 12:47:46 +00002987 this->skip_user_consent = skip_user_consent;
Nandana Dutt54dbd672019-01-11 12:58:05 +00002988 // Duplicate the fds because the passed in fds don't outlive the binder transaction.
Todd Frederick621533f2022-03-26 02:54:17 +00002989 bugreport_fd.reset(fcntl(bugreport_fd_in.get(), F_DUPFD_CLOEXEC, 0));
2990 screenshot_fd.reset(fcntl(screenshot_fd_in.get(), F_DUPFD_CLOEXEC, 0));
Nandana Dutt58d72e22018-11-16 10:30:48 +00002991
Paul Changf59c2b72020-03-10 02:08:55 +08002992 SetOptionsFromMode(bugreport_mode, this, is_screenshot_requested);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002993}
2994
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002995Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
2996 RunStatus status = RunStatus::OK;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002997 int c;
mhasankd451a472020-05-26 18:02:39 -07002998 while ((c = getopt(argc, argv, "dho:svqzpLPBRSV:w")) != -1) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002999 switch (c) {
3000 // clang-format off
mhasank3a4cfb42020-06-15 18:06:43 -07003001 case 'o': out_dir = optarg; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003002 case 's': stream_to_socket = true; break;
3003 case 'S': progress_updates_to_socket = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003004 case 'v': show_header_only = true; break;
3005 case 'q': do_vibrate = false; break;
Paul Chang0d2aad72020-02-13 20:04:03 +08003006 case 'p': do_screenshot = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003007 case 'P': do_progress_updates = true; break;
3008 case 'R': is_remote_mode = true; break;
mhasankd451a472020-05-26 18:02:39 -07003009 case 'L': limited_only = true; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003010 case 'V':
3011 case 'd':
3012 case 'z':
3013 // compatibility no-op
3014 break;
Nandana Dutt235864b2019-01-22 12:10:16 +00003015 case 'w':
3016 // This was already processed
3017 break;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003018 case 'h':
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003019 status = RunStatus::HELP;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003020 break;
3021 default:
3022 fprintf(stderr, "Invalid option: %c\n", c);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003023 status = RunStatus::INVALID_INPUT;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003024 break;
3025 // clang-format on
3026 }
3027 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08003028
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003029 for (int i = 0; i < argc; i++) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003030 args += argv[i];
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003031 if (i < argc - 1) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003032 args += " ";
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003033 }
3034 }
3035
3036 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
3037 optind = 1;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003038
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003039 return status;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003040}
3041
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003042bool Dumpstate::DumpOptions::ValidateOptions() const {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003043 if (bugreport_fd.get() != -1 && stream_to_socket) {
Nandana Dutt979388e2018-11-30 16:48:55 +00003044 return false;
3045 }
3046
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003047 if ((progress_updates_to_socket || do_progress_updates) && stream_to_socket) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003048 return false;
3049 }
3050
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003051 if (is_remote_mode && (do_progress_updates || stream_to_socket)) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003052 return false;
3053 }
3054 return true;
3055}
3056
Nandana Dutt197661d2018-11-16 16:40:21 +00003057void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
3058 options_ = std::move(options);
3059}
3060
Abhijeet Kaura407fb82020-03-27 12:51:12 +00003061void Dumpstate::Initialize() {
3062 /* gets the sequential id */
3063 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
3064 id_ = ++last_id;
3065 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
3066}
3067
Nandana Duttd2f5f082019-01-18 17:13:52 +00003068Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
3069 Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
Gavin Corkerya44686c2022-11-23 18:16:51 +00003070 HandleRunStatus(status);
3071 return status;
3072}
3073
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003074Dumpstate::RunStatus Dumpstate::Retrieve(int32_t calling_uid, const std::string& calling_package,
Kholoud Mohameddef4e432024-05-15 12:47:46 +00003075 const bool keep_bugreport_on_retrieval,
3076 const bool skip_user_consent) {
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003077 Dumpstate::RunStatus status = RetrieveInternal(calling_uid, calling_package,
Kholoud Mohameddef4e432024-05-15 12:47:46 +00003078 keep_bugreport_on_retrieval,
3079 skip_user_consent);
Gavin Corkerya44686c2022-11-23 18:16:51 +00003080 HandleRunStatus(status);
3081 return status;
3082}
3083
3084Dumpstate::RunStatus Dumpstate::RetrieveInternal(int32_t calling_uid,
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003085 const std::string& calling_package,
Kholoud Mohameddef4e432024-05-15 12:47:46 +00003086 const bool keep_bugreport_on_retrieval,
3087 const bool skip_user_consent) {
3088 if (!android::app::admin::flags::onboarding_consentless_bugreports() || !skip_user_consent) {
3089 consent_callback_ = new ConsentCallback();
3090 const String16 incidentcompanion("incidentcompanion");
3091 sp<android::IBinder> ics(
3092 defaultServiceManager()->checkService(incidentcompanion));
3093 android::String16 package(calling_package.c_str());
3094 if (ics != nullptr) {
3095 MYLOGD("Checking user consent via incidentcompanion service\n");
3096
3097 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
3098 calling_uid, package, String16(), String16(),
3099 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
3100 } else {
3101 MYLOGD(
3102 "Unable to check user consent; incidentcompanion service unavailable\n");
3103 return RunStatus::USER_CONSENT_TIMED_OUT;
3104 }
3105 UserConsentResult consent_result = consent_callback_->getResult();
3106 int timeout_ms = 30 * 1000;
3107 while (consent_result == UserConsentResult::UNAVAILABLE &&
3108 consent_callback_->getElapsedTimeMs() < timeout_ms) {
3109 sleep(1);
3110 consent_result = consent_callback_->getResult();
3111 }
3112 if (consent_result == UserConsentResult::DENIED) {
3113 return RunStatus::USER_CONSENT_DENIED;
3114 }
3115 if (consent_result == UserConsentResult::UNAVAILABLE) {
3116 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3117 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3118 consent_callback_.get());
3119 return RunStatus::USER_CONSENT_TIMED_OUT;
3120 }
Gavin Corkerya44686c2022-11-23 18:16:51 +00003121 }
3122
3123 bool copy_succeeded =
3124 android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003125
3126 if (copy_succeeded && (!android::app::admin::flags::onboarding_bugreport_v2_enabled()
3127 || !keep_bugreport_on_retrieval)) {
3128 android::os::UnlinkAndLogOnError(path_);
Gavin Corkerya44686c2022-11-23 18:16:51 +00003129 }
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003130
Gavin Corkerya44686c2022-11-23 18:16:51 +00003131 return copy_succeeded ? Dumpstate::RunStatus::OK
3132 : Dumpstate::RunStatus::ERROR;
3133}
3134
3135void Dumpstate::HandleRunStatus(Dumpstate::RunStatus status) {
3136 if (listener_ != nullptr) {
Nandana Duttbabf6c72019-01-15 14:11:12 +00003137 switch (status) {
3138 case Dumpstate::RunStatus::OK:
Gavin Corkerya44686c2022-11-23 18:16:51 +00003139 listener_->onFinished(path_.c_str());
Nandana Duttbabf6c72019-01-15 14:11:12 +00003140 break;
3141 case Dumpstate::RunStatus::HELP:
3142 break;
3143 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003144 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00003145 break;
3146 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003147 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
3148 break;
3149 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3150 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
3151 break;
3152 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
3153 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00003154 break;
3155 }
3156 }
Nandana Duttbabf6c72019-01-15 14:11:12 +00003157}
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003158void Dumpstate::Cancel() {
3159 CleanupTmpFiles();
3160 android::os::UnlinkAndLogOnError(log_path_);
3161 for (int i = 0; i < NUM_OF_DUMPS; i++) {
3162 android::os::UnlinkAndLogOnError(ds.bugreport_internal_dir_ + "/" +
3163 kDumpstateBoardFiles[i]);
3164 }
3165 tombstone_data_.clear();
3166 anr_data_.clear();
Andy Hungd62f7e62024-01-11 15:47:52 -08003167 anr_trace_data_.clear();
Woody Lin20767a92022-11-29 15:50:24 +08003168 shutdown_checkpoints_.clear();
Rhed Jao0daac912020-08-21 14:48:20 +08003169
3170 // Instead of shutdown the pool, we delete temporary files directly since
3171 // shutdown blocking the call.
3172 if (dump_pool_) {
3173 dump_pool_->deleteTempFiles();
3174 }
3175 if (zip_entry_tasks_) {
3176 zip_entry_tasks_->run(/*do_cancel =*/ true);
3177 }
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003178}
3179
Kean Mariotti306633e2022-09-05 16:30:47 +00003180void Dumpstate::PreDumpUiData() {
Kean Mariottica20f2d2023-12-15 09:34:25 +00003181 auto snapshot_system_trace = MaybeSnapshotSystemTraceAsync();
Kean Mariotti306633e2022-09-05 16:30:47 +00003182 MaybeSnapshotUiTraces();
Kean Mariottica20f2d2023-12-15 09:34:25 +00003183 MaybeWaitForSnapshotSystemTrace(std::move(snapshot_system_trace));
Kean Mariotti306633e2022-09-05 16:30:47 +00003184}
3185
Nandana Dutt979388e2018-11-30 16:48:55 +00003186/*
3187 * Dumps relevant information to a bugreport based on the given options.
3188 *
3189 * The bugreport can be dumped to a file or streamed to a socket.
3190 *
3191 * How dumping to file works:
3192 * stdout is redirected to a temporary file. This will later become the main bugreport entry.
3193 * stderr is redirected a log file.
3194 *
3195 * The temporary bugreport is then populated via printfs, dumping contents of files and
3196 * output of commands to stdout.
3197 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003198 * A bunch of other files and dumps are added to the zip archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00003199 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003200 * The temporary bugreport file and the log file also get added to the archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00003201 *
mhasank2d75c442020-06-11 15:05:25 -07003202 * Bugreports are first generated in a local directory and later copied to the caller's fd
3203 * or directory if supplied.
Nandana Dutt979388e2018-11-30 16:48:55 +00003204 */
Nandana Duttd2f5f082019-01-18 17:13:52 +00003205Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
3206 const std::string& calling_package) {
Rhed Jao5377d792020-07-16 17:37:39 +08003207 DurationReporter duration_reporter("RUN INTERNAL", /* logcat_only = */true);
Nandana Dutt979388e2018-11-30 16:48:55 +00003208 LogDumpOptions(*options_);
Nandana Dutt197661d2018-11-16 16:40:21 +00003209 if (!options_->ValidateOptions()) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00003210 MYLOGE("Invalid options specified\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003211 return RunStatus::INVALID_INPUT;
3212 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003213 /* set as high priority, and protect from OOM killer */
3214 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003215
Felipe Lemed071c682016-10-20 16:48:00 -07003216 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07003217 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003218 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003219 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003220 } else {
3221 /* fallback to kernels <= 2.6.35 */
3222 oom_adj = fopen("/proc/self/oom_adj", "we");
3223 if (oom_adj) {
3224 fputs("-17", oom_adj);
3225 fclose(oom_adj);
3226 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003227 }
3228
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003229 if (version_ == VERSION_DEFAULT) {
3230 version_ = VERSION_CURRENT;
Michal Karpinski4db754f2015-12-11 18:04:32 +00003231 }
3232
Chris Morin5a50d482022-02-01 17:41:18 -08003233 if (version_ != VERSION_CURRENT) {
3234 MYLOGE("invalid version requested ('%s'); supported values are: ('%s', '%s')\n",
3235 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003236 return RunStatus::INVALID_INPUT;
Felipe Lemed071c682016-10-20 16:48:00 -07003237 }
3238
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003239 if (options_->show_header_only) {
3240 PrintHeader();
3241 return RunStatus::OK;
Felipe Lemed071c682016-10-20 16:48:00 -07003242 }
3243
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003244 MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n",
3245 calling_uid, calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003246
Felipe Leme7447d7c2016-11-03 18:12:22 -07003247 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003248 std::string stats_path =
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003249 android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003250 progress_.reset(new Progress(stats_path));
Felipe Leme7447d7c2016-11-03 18:12:22 -07003251
Sahana Raof35ed432019-07-12 10:47:52 +01003252 if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
3253 MYLOGE("Failed to acquire wake lock: %s\n", strerror(errno));
3254 } else {
3255 // Wake lock will be released automatically on process death
3256 MYLOGD("Wake lock acquired.\n");
3257 }
3258
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08003259 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07003260
Felipe Lemef0292972016-11-22 13:57:05 -08003261 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07003262 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
3263 }
3264
Kevin Jeonfa64e642023-07-27 11:36:41 -04003265 if (PropertiesHelper::IsStrictRun()) {
3266 MYLOGI(
3267 "Running on strict-run mode, which has shorter timeouts "
3268 "(to disable, call 'setprop dumpstate.strict_run false')\n");
3269 }
3270
Nandana Dutt235c6672019-11-14 15:22:32 +00003271 MYLOGI("dumpstate info: id=%d, args='%s', bugreport_mode= %s bugreport format version: %s\n",
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00003272 id_, options_->args.c_str(), options_->bugreport_mode_string.c_str(), version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08003273
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003274 do_early_screenshot_ = options_->do_progress_updates;
Felipe Lemee338bf62015-12-07 14:03:50 -08003275
Christopher Ferrised9354f2014-10-01 17:35:01 -07003276 // If we are going to use a socket, do it as early as possible
3277 // to avoid timeouts from bugreport.
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003278 if (options_->stream_to_socket || options_->progress_updates_to_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07003279 MYLOGD("Opening control socket\n");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003280 control_socket_fd_ = open_socket_fn_("dumpstate");
Nandana Dutta344cb62019-02-22 15:12:35 +00003281 if (control_socket_fd_ == -1) {
3282 return ERROR;
3283 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003284 if (options_->progress_updates_to_socket) {
3285 options_->do_progress_updates = 1;
3286 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07003287 }
3288
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003289 if (!PrepareToWriteToFile()) {
3290 return ERROR;
3291 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08003292
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003293 // Interactive, wear & telephony modes are default to true.
3294 // and may enable from cli option or when using control socket
3295 if (options_->do_progress_updates) {
3296 // clang-format off
3297 std::vector<std::string> am_args = {
3298 "--receiver-permission", "android.permission.DUMP",
3299 };
3300 // clang-format on
3301 // Send STARTED broadcast for apps that listen to bugreport generation events
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003302 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED",
3303 am_args, multiuser_get_user_id(calling_uid));
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003304 if (options_->progress_updates_to_socket) {
3305 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08003306 }
3307 }
3308
Nick Kralevichf3599b32016-01-25 15:05:16 -08003309 /* read /proc/cmdline before dropping root */
3310 FILE *cmdline = fopen("/proc/cmdline", "re");
3311 if (cmdline) {
3312 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
3313 fclose(cmdline);
3314 }
3315
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003316 if (options_->do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08003317 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05003318 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003319
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003320 if (zip_file != nullptr) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003321 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
3322 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003323 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08003324 }
3325 }
3326
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003327 int dup_stdout_fd;
3328 int dup_stderr_fd;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003329 // Redirect stderr to log_path_ for debugging.
3330 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
3331 if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
3332 return ERROR;
3333 }
3334 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
3335 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
3336 strerror(errno));
3337 }
Nandana Dutt979388e2018-11-30 16:48:55 +00003338
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003339 // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
3340 // moved into zip file later, if zipping.
3341 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
3342 // TODO: why not write to a file instead of stdout to overcome this problem?
3343 /* TODO: rather than generating a text file now and zipping it later,
3344 it would be more efficient to redirect stdout to the zip entry
3345 directly, but the libziparchive doesn't support that option yet. */
3346 if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
3347 return ERROR;
3348 }
3349 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
3350 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
3351 tmp_path_.c_str(), strerror(errno));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003352 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08003353
3354 // Don't buffer stdout
3355 setvbuf(stdout, nullptr, _IONBF, 0);
3356
Rhed Jao5377d792020-07-16 17:37:39 +08003357 // Enable the parallel run if the client requests to output to a file.
3358 EnableParallelRunIfNeeded();
3359 // Using scope guard to make sure the dump pool can be shut down correctly.
3360 auto scope_guard_to_shutdown_pool = android::base::make_scope_guard([=]() {
3361 ShutdownDumpPool();
3362 });
3363
Felipe Leme608385d2016-02-01 10:35:38 -08003364 // NOTE: there should be no stdout output until now, otherwise it would break the header.
3365 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08003366 // duration is logged into MYLOG instead.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003367 PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003368
Kean Mariottic14cebc2024-03-04 10:55:28 +00003369 bool system_trace_exists = access(SYSTEM_TRACE_SNAPSHOT, F_OK) == 0;
3370 if (options_->use_predumped_ui_data && !system_trace_exists) {
3371 MYLOGW("Ignoring 'use predumped data' flag because no predumped data is available");
3372 options_->use_predumped_ui_data = false;
3373 }
3374
Kean Mariottica20f2d2023-12-15 09:34:25 +00003375 std::future<std::string> snapshot_system_trace;
3376
Kean Mariotti853b73a2023-07-27 12:40:30 +00003377 bool is_dumpstate_restricted =
3378 options_->telephony_only || options_->wifi_only || options_->limited_only;
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003379 if (!is_dumpstate_restricted) {
3380 // Snapshot the system trace now (if running) to avoid that dumpstate's
3381 // own activity pushes out interesting data from the trace ring buffer.
3382 // The trace file is added to the zip by MaybeAddSystemTraceToZip().
Kean Mariottica20f2d2023-12-15 09:34:25 +00003383 snapshot_system_trace = MaybeSnapshotSystemTraceAsync();
Yohei Yukawa95305b32021-03-09 07:54:27 -08003384
Kean Mariotti853b73a2023-07-27 12:40:30 +00003385 // Invoke critical dumpsys to preserve system state, before doing anything else.
3386 RunDumpsysCritical();
3387
Kean Mariotti306633e2022-09-05 16:30:47 +00003388 // Snapshot the UI traces now (if running).
3389 // The trace files will be added to bugreport later.
3390 MaybeSnapshotUiTraces();
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003391 }
Kean Mariotti853b73a2023-07-27 12:40:30 +00003392
3393 MaybeTakeEarlyScreenshot();
Kean Mariottica20f2d2023-12-15 09:34:25 +00003394 MaybeWaitForSnapshotSystemTrace(std::move(snapshot_system_trace));
Gavin Corkery6968f552020-11-22 18:09:05 +00003395 onUiIntensiveBugreportDumpsFinished(calling_uid);
3396 MaybeCheckUserConsent(calling_uid, calling_package);
3397 if (options_->telephony_only) {
3398 DumpstateTelephonyOnly(calling_package);
3399 } else if (options_->wifi_only) {
3400 DumpstateWifiOnly();
3401 } else if (options_->limited_only) {
3402 DumpstateLimitedOnly();
Elis Elliott8e401ad2023-08-08 11:18:59 +00003403 } else if (options_->onboarding_only) {
3404 DumpstateOnboardingOnly();
Gavin Corkery6968f552020-11-22 18:09:05 +00003405 } else {
Nandana Dutt4be45d12018-09-26 15:04:23 +01003406 // Dump state for the default case. This also drops root.
Jichao Lie89d9c12019-11-21 19:02:51 -08003407 RunStatus s = DumpstateDefaultAfterCritical();
Nandana Dutt5c390032019-03-12 10:52:56 +00003408 if (s != RunStatus::OK) {
Nandana Duttaac6f582019-07-26 14:32:47 +01003409 if (s == RunStatus::USER_CONSENT_DENIED) {
Nandana Dutt5c390032019-03-12 10:52:56 +00003410 HandleUserConsentDenied();
3411 }
3412 return s;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08003413 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07003414 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07003415
Felipe Leme55b42a62015-11-10 17:39:08 -08003416 /* close output if needed */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003417 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003418
Abhijeet Kaure370d682019-10-01 16:49:30 +01003419 // Zip the (now complete) .tmp file within the internal directory.
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003420 ATRACE_BEGIN("FinalizeFile");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003421 FinalizeFile();
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003422 ATRACE_END();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003423
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003424 // Share the final file with the caller if the user has consented or Shell is the caller.
Nandana Duttd2f5f082019-01-18 17:13:52 +00003425 Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
Gavin Corkerya44686c2022-11-23 18:16:51 +00003426 if (CalledByApi() && !options_->is_consent_deferred) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003427 status = CopyBugreportIfUserConsented(calling_uid);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003428 if (status != Dumpstate::RunStatus::OK &&
3429 status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3430 // Do an early return if there were errors. We make an exception for consent
3431 // timing out because it's possible the user got distracted. In this case the
3432 // bugreport is not shared but made available for manual retrieval.
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003433 MYLOGI("User denied consent. Returning\n");
Nandana Duttd2f5f082019-01-18 17:13:52 +00003434 return status;
3435 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003436 if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3437 MYLOGI(
3438 "Did not receive user consent yet."
3439 " Will not copy the bugreport artifacts to caller.\n");
Abhijeet Kaur57627412019-04-17 16:00:09 +01003440 const String16 incidentcompanion("incidentcompanion");
3441 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
3442 if (ics != nullptr) {
3443 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3444 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3445 consent_callback_.get());
3446 } else {
3447 MYLOGD("Unable to cancel user consent; incidentcompanion service unavailable\n");
3448 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003449 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003450 }
3451
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003452 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003453 if (options_->do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09003454 for (int i = 0; i < 3; i++) {
3455 Vibrate(75);
3456 usleep((75 + 50) * 1000);
3457 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003458 }
3459
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003460 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
3461 progress_->GetInitialMax());
3462 progress_->Save();
3463 MYLOGI("done (id %d)\n", id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003464
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003465 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08003466
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003467 if (control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07003468 MYLOGD("Closing control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003469 close(control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07003470 }
3471
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003472 tombstone_data_.clear();
3473 anr_data_.clear();
Andy Hungd62f7e62024-01-11 15:47:52 -08003474 anr_trace_data_.clear();
Woody Lin20767a92022-11-29 15:50:24 +08003475 shutdown_checkpoints_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01003476
Nandana Duttd2f5f082019-01-18 17:13:52 +00003477 return (consent_callback_ != nullptr &&
3478 consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
3479 ? USER_CONSENT_TIMED_OUT
3480 : RunStatus::OK;
3481}
3482
Paul Chang0d2aad72020-02-13 20:04:03 +08003483void Dumpstate::MaybeTakeEarlyScreenshot() {
3484 if (!options_->do_screenshot || !do_early_screenshot_) {
3485 return;
3486 }
3487
3488 TakeScreenshot();
3489}
3490
Kean Mariottica20f2d2023-12-15 09:34:25 +00003491std::future<std::string> Dumpstate::MaybeSnapshotSystemTraceAsync() {
Kean Mariotti853b73a2023-07-27 12:40:30 +00003492 // When capturing traces via bugreport handler (BH), this function will be invoked twice:
3493 // 1) When BH invokes IDumpstate::PreDumpUiData()
3494 // 2) When BH invokes IDumpstate::startBugreport(flags = BUGREPORT_USE_PREDUMPED_UI_DATA)
3495 // In this case we don't want to re-invoke perfetto in step 2.
3496 // In all other standard invocation states, this function is invoked once
3497 // without the flag BUGREPORT_USE_PREDUMPED_UI_DATA.
Kean Mariottica20f2d2023-12-15 09:34:25 +00003498 // This function must run asynchronously to avoid delaying MaybeTakeEarlyScreenshot() in the
3499 // standard invocation states (b/316110955).
Kean Mariotti853b73a2023-07-27 12:40:30 +00003500 if (options_->use_predumped_ui_data) {
Kean Mariottica20f2d2023-12-15 09:34:25 +00003501 return {};
3502 }
3503
3504 // Create temporary file for the command's output
3505 std::string outPath = ds.bugreport_internal_dir_ + "/tmp_serialize_perfetto_trace";
3506 auto outFd = android::base::unique_fd(TEMP_FAILURE_RETRY(
3507 open(outPath.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
3508 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
3509 if (outFd < 0) {
3510 MYLOGE("Could not open %s to serialize perfetto trace.\n", outPath.c_str());
3511 return {};
Kean Mariotti853b73a2023-07-27 12:40:30 +00003512 }
3513
3514 // If a stale file exists already, remove it.
3515 unlink(SYSTEM_TRACE_SNAPSHOT);
3516
Kean Mariottica20f2d2023-12-15 09:34:25 +00003517 MYLOGI("Launching async '%s'", SERIALIZE_PERFETTO_TRACE_TASK.c_str())
3518 return std::async(
3519 std::launch::async, [this, outPath = std::move(outPath), outFd = std::move(outFd)] {
3520 // If a background system trace is happening and is marked as "suitable for
3521 // bugreport" (i.e. bugreport_score > 0 in the trace config), this command
3522 // will stop it and serialize into SYSTEM_TRACE_SNAPSHOT. In the (likely)
3523 // case that no trace is ongoing, this command is a no-op.
3524 // Note: this should not be enqueued as we need to freeze the trace before
3525 // dumpstate starts. Otherwise the trace ring buffers will contain mostly
3526 // the dumpstate's own activity which is irrelevant.
3527 RunCommand(
3528 SERIALIZE_PERFETTO_TRACE_TASK, {"perfetto", "--save-for-bugreport"},
3529 CommandOptions::WithTimeout(10).DropRoot().CloseAllFileDescriptorsOnExec().Build(),
3530 false, outFd);
3531 // MaybeAddSystemTraceToZip() will take care of copying the trace in the zip
3532 // file in the later stages.
3533
3534 return outPath;
3535 });
3536}
3537
3538void Dumpstate::MaybeWaitForSnapshotSystemTrace(std::future<std::string> task) {
3539 if (!task.valid()) {
3540 return;
3541 }
3542
3543 WaitForTask(std::move(task), SERIALIZE_PERFETTO_TRACE_TASK, STDOUT_FILENO);
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003544}
3545
Kean Mariotti306633e2022-09-05 16:30:47 +00003546void Dumpstate::MaybeSnapshotUiTraces() {
3547 if (PropertiesHelper::IsUserBuild() || options_->use_predumped_ui_data) {
3548 return;
3549 }
3550
Pablo Gamito654831c2024-02-16 16:47:48 +00003551 std::vector<std::vector<std::string>> dumpTracesForBugReportCommands = {
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003552 {"cmd", "input_method", "tracing", "save-for-bugreport"},
3553 {"cmd", "window", "tracing", "save-for-bugreport"},
3554 {"cmd", "window", "shell", "tracing", "save-for-bugreport"},
3555 };
Hongwei Wang39229132023-01-24 15:09:59 -08003556
Pablo Gamito654831c2024-02-16 16:47:48 +00003557 if (!android_tracing_perfetto_transition_tracing()) {
3558 dumpTracesForBugReportCommands.push_back({"dumpsys", "activity", "service",
3559 "SystemUIService", "WMShell", "transitions",
3560 "tracing", "save-for-bugreport"});
3561 }
3562
Pablo Gamito6929a0e2024-02-26 23:29:47 +00003563 if (!android_tracing_perfetto_protolog_tracing()) {
Pablo Gamito654831c2024-02-16 16:47:48 +00003564 dumpTracesForBugReportCommands.push_back({"dumpsys", "activity", "service",
3565 "SystemUIService", "WMShell", "protolog",
3566 "save-for-bugreport"});
3567 }
3568
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003569 for (const auto& command : dumpTracesForBugReportCommands) {
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003570 RunCommand(
3571 // Empty name because it's not intended to be classified as a bugreport section.
3572 // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003573 "", command,
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003574 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
3575 }
Kean Mariotti306633e2022-09-05 16:30:47 +00003576}
3577
3578void Dumpstate::MaybeAddUiTracesToZip() {
3579 if (PropertiesHelper::IsUserBuild()) {
3580 return;
3581 }
3582
3583 ds.AddDir(WMTRACE_DATA_DIR, false);
Yohei Yukawa95305b32021-03-09 07:54:27 -08003584}
3585
Paul Changeb4b4642020-05-28 22:05:47 +08003586void Dumpstate::onUiIntensiveBugreportDumpsFinished(int32_t calling_uid) {
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003587 if (multiuser_get_app_id(calling_uid) == AID_SHELL || !CalledByApi()) {
Paul Changc490e662020-04-11 18:14:09 +08003588 return;
3589 }
3590 if (listener_ != nullptr) {
3591 // Let listener know ui intensive bugreport dumps are finished, then it can do event
3592 // handling if required.
Paul Changeb4b4642020-05-28 22:05:47 +08003593 listener_->onUiIntensiveBugreportDumpsFinished();
Paul Changc490e662020-04-11 18:14:09 +08003594 }
3595}
3596
Jichao Lie89d9c12019-11-21 19:02:51 -08003597void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) {
Gavin Corkerya44686c2022-11-23 18:16:51 +00003598 if (multiuser_get_app_id(calling_uid) == AID_SHELL ||
Kholoud Mohameddef4e432024-05-15 12:47:46 +00003599 !CalledByApi() || options_->is_consent_deferred ||
3600 (android::app::admin::flags::onboarding_consentless_bugreports() &&
3601 options_->skip_user_consent)) {
Gavin Corkerya44686c2022-11-23 18:16:51 +00003602 // No need to get consent for shell triggered dumpstates, or not
3603 // through bugreporting API (i.e. no fd to copy back), or when consent
3604 // is deferred.
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003605 return;
3606 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003607 consent_callback_ = new ConsentCallback();
3608 const String16 incidentcompanion("incidentcompanion");
3609 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
Jichao Lie89d9c12019-11-21 19:02:51 -08003610 android::String16 package(calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003611 if (ics != nullptr) {
3612 MYLOGD("Checking user consent via incidentcompanion service\n");
Steven Leeb573eb82022-11-29 22:31:35 +08003613 int flags = 0x1; // IncidentManager.FLAG_CONFIRMATION_DIALOG
3614 if (IsConsentlessBugreportAllowed(*options_)) {
3615 flags |= 0x2; // IncidentManager.FLAG_ALLOW_CONSENTLESS_BUGREPORT
3616 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003617 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
Steven Leeb573eb82022-11-29 22:31:35 +08003618 calling_uid, package, String16(), String16(), flags, consent_callback_.get());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003619 } else {
3620 MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
3621 }
3622}
3623
Nandana Dutt5c390032019-03-12 10:52:56 +00003624bool Dumpstate::IsUserConsentDenied() const {
3625 return ds.consent_callback_ != nullptr &&
3626 ds.consent_callback_->getResult() == UserConsentResult::DENIED;
3627}
3628
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01003629bool Dumpstate::CalledByApi() const {
3630 return ds.options_->bugreport_fd.get() != -1 ? true : false;
3631}
3632
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003633void Dumpstate::CleanupTmpFiles() {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003634 android::os::UnlinkAndLogOnError(tmp_path_);
3635 android::os::UnlinkAndLogOnError(screenshot_path_);
3636 android::os::UnlinkAndLogOnError(path_);
Gavin Corkery789d7a52021-02-24 23:52:35 +00003637 if (dump_traces_path != nullptr) {
3638 android::os::UnlinkAndLogOnError(dump_traces_path);
3639 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003640}
3641
Rhed Jao5377d792020-07-16 17:37:39 +08003642void Dumpstate::EnableParallelRunIfNeeded() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003643 if (!PropertiesHelper::IsParallelRun()) {
Rhed Jao5377d792020-07-16 17:37:39 +08003644 return;
3645 }
3646 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003647 zip_entry_tasks_ = std::make_unique<TaskQueue>();
Rhed Jao5377d792020-07-16 17:37:39 +08003648}
3649
3650void Dumpstate::ShutdownDumpPool() {
3651 if (dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08003652 dump_pool_.reset();
Rhed Jao5377d792020-07-16 17:37:39 +08003653 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003654 if (zip_entry_tasks_) {
3655 zip_entry_tasks_->run(/* do_cancel = */true);
3656 zip_entry_tasks_ = nullptr;
3657 }
3658}
3659
3660void Dumpstate::EnqueueAddZipEntryAndCleanupIfNeeded(const std::string& entry_name,
3661 const std::string& entry_path) {
3662 auto func_add_zip_entry_and_cleanup = [=](bool task_cancelled) {
3663 if (!task_cancelled) {
3664 AddZipEntry(entry_name, entry_path);
3665 }
3666 android::os::UnlinkAndLogOnError(entry_path);
3667 };
3668 if (zip_entry_tasks_) {
3669 // Enqueues AddZipEntryAndCleanup function if the parallel run is enabled.
3670 zip_entry_tasks_->add(func_add_zip_entry_and_cleanup, _1);
3671 } else {
3672 // Invokes AddZipEntryAndCleanup immediately
3673 std::invoke(func_add_zip_entry_and_cleanup, /* task_cancelled = */false);
3674 }
Rhed Jao5377d792020-07-16 17:37:39 +08003675}
3676
Nandana Duttd2f5f082019-01-18 17:13:52 +00003677Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
3678 MYLOGD("User denied consent; deleting files and returning\n");
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003679 CleanupTmpFiles();
Nandana Duttd2f5f082019-01-18 17:13:52 +00003680 return USER_CONSENT_DENIED;
3681}
3682
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003683Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented(int32_t calling_uid) {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003684 // If the caller has asked to copy the bugreport over to their directory, we need explicit
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003685 // user consent (unless the caller is Shell).
3686 UserConsentResult consent_result;
Kholoud Mohameddef4e432024-05-15 12:47:46 +00003687 if (multiuser_get_app_id(calling_uid) == AID_SHELL || (options_->skip_user_consent
3688 && android::app::admin::flags::onboarding_consentless_bugreports())) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003689 consent_result = UserConsentResult::APPROVED;
3690 } else {
3691 consent_result = consent_callback_->getResult();
3692 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003693 if (consent_result == UserConsentResult::UNAVAILABLE) {
3694 // User has not responded yet.
3695 uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
Hunter Knepshield70610fa2020-01-03 15:27:33 -08003696 // Telephony is a fast report type, particularly on user builds where information may be
3697 // more aggressively limited. To give the user time to read the consent dialog, increase the
3698 // timeout.
3699 uint64_t timeout_ms = options_->telephony_only ? TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS
3700 : USER_CONSENT_TIMEOUT_MS;
3701 if (elapsed_ms < timeout_ms) {
3702 uint delay_seconds = (timeout_ms - elapsed_ms) / 1000;
Nandana Duttd2f5f082019-01-18 17:13:52 +00003703 MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
3704 sleep(delay_seconds);
3705 }
3706 consent_result = consent_callback_->getResult();
3707 }
3708 if (consent_result == UserConsentResult::DENIED) {
3709 // User has explicitly denied sharing with the app. To be safe delete the
3710 // internal bugreport & tmp files.
3711 return HandleUserConsentDenied();
3712 }
3713 if (consent_result == UserConsentResult::APPROVED) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00003714 bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
3715 if (copy_succeeded) {
3716 android::os::UnlinkAndLogOnError(path_);
Abhijeet Kaur9ce94672020-04-01 17:22:36 +01003717 if (options_->do_screenshot &&
3718 options_->screenshot_fd.get() != -1 &&
3719 !options_->is_screenshot_copied) {
3720 copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
3721 options_->screenshot_fd.get());
3722 options_->is_screenshot_copied = copy_succeeded;
3723 if (copy_succeeded) {
3724 android::os::UnlinkAndLogOnError(screenshot_path_);
3725 }
3726 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003727 }
3728 return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
3729 } else if (consent_result == UserConsentResult::UNAVAILABLE) {
3730 // consent_result is still UNAVAILABLE. The user has likely not responded yet.
3731 // Since we do not have user consent to share the bugreport it does not get
3732 // copied over to the calling app but remains in the internal directory from
3733 // where the user can manually pull it.
Paul Changce644212021-05-11 16:06:45 +08003734 std::string final_path = GetPath(".zip");
3735 bool copy_succeeded = android::os::CopyFileToFile(path_, final_path);
3736 if (copy_succeeded) {
3737 android::os::UnlinkAndLogOnError(path_);
3738 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003739 return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
3740 }
3741 // Unknown result; must be a programming error.
3742 MYLOGE("Unknown user consent result:%d\n", consent_result);
3743 return Dumpstate::RunStatus::ERROR;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003744}
3745
Nandana Duttf02564e2019-02-15 15:24:24 +00003746Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003747 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
3748 Dumpstate::RunStatus status = options->Initialize(argc, argv);
3749 if (status == Dumpstate::RunStatus::OK) {
Nandana Duttf02564e2019-02-15 15:24:24 +00003750 SetOptions(std::move(options));
Nandana Duttd2f5f082019-01-18 17:13:52 +00003751 // When directly running dumpstate binary, the output is not expected to be written
3752 // to any external file descriptor.
Nandana Duttf02564e2019-02-15 15:24:24 +00003753 assert(options_->bugreport_fd.get() == -1);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003754
3755 // calling_uid and calling_package are for user consent to share the bugreport with
Abhijeet Kaura407fb82020-03-27 12:51:12 +00003756 // an app; they are irrelevant here because bugreport is triggered via command line.
3757 // Update Last ID before calling Run().
3758 Initialize();
Nikhil Kumarb70622a2023-06-15 15:37:19 +01003759 status = Run(0 /* calling_uid */, "" /* calling_package */);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003760 }
Nandana Duttf02564e2019-02-15 15:24:24 +00003761 return status;
3762}
3763
3764/* Main entry point for dumpstate binary. */
3765int run_main(int argc, char* argv[]) {
3766 Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003767
3768 switch (status) {
3769 case Dumpstate::RunStatus::OK:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003770 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003771 case Dumpstate::RunStatus::HELP:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003772 ShowUsage();
3773 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003774 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003775 fprintf(stderr, "Invalid combination of args\n");
3776 ShowUsage();
3777 exit(1);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003778 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003779 FALLTHROUGH_INTENDED;
3780 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3781 FALLTHROUGH_INTENDED;
3782 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003783 exit(2);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003784 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003785}
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003786
3787// TODO(111441001): Default DumpOptions to sensible values.
3788Dumpstate::Dumpstate(const std::string& version)
3789 : pid_(getpid()),
3790 options_(new Dumpstate::DumpOptions()),
Nandana Dutt402a8392019-06-14 14:25:13 +01003791 last_reported_percent_progress_(0),
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003792 version_(version),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003793 now_(time(nullptr)),
3794 open_socket_fn_(open_socket) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003795}
3796
3797Dumpstate& Dumpstate::GetInstance() {
3798 static Dumpstate singleton_(android::base::GetProperty("dumpstate.version", VERSION_CURRENT));
3799 return singleton_;
3800}
3801
Rhed Jao5377d792020-07-16 17:37:39 +08003802DurationReporter::DurationReporter(const std::string& title, bool logcat_only, bool verbose,
3803 int duration_fd) : title_(title), logcat_only_(logcat_only), verbose_(verbose),
3804 duration_fd_(duration_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003805 if (!title_.empty()) {
3806 started_ = Nanotime();
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003807 if (title_.find("SHOW MAP") == std::string::npos) {
3808 ATRACE_ASYNC_BEGIN(title_.c_str(), 0);
3809 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003810 }
3811}
3812
3813DurationReporter::~DurationReporter() {
3814 if (!title_.empty()) {
3815 float elapsed = (float)(Nanotime() - started_) / NANOS_PER_SEC;
chenqiwuaf8b2d92019-12-12 18:53:51 +08003816 if (elapsed >= .5f || verbose_) {
3817 MYLOGD("Duration of '%s': %.2fs\n", title_.c_str(), elapsed);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003818 }
chenqiwuaf8b2d92019-12-12 18:53:51 +08003819 if (!logcat_only_) {
3820 // Use "Yoda grammar" to make it easier to grep|sort sections.
Rhed Jao5377d792020-07-16 17:37:39 +08003821 dprintf(duration_fd_, "------ %.3fs was the duration of '%s' ------\n",
3822 elapsed, title_.c_str());
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003823 }
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003824 if (title_.find("SHOW MAP") == std::string::npos) {
3825 ATRACE_ASYNC_END(title_.c_str(), 0);
3826 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003827 }
3828}
3829
3830const int32_t Progress::kDefaultMax = 5000;
3831
3832Progress::Progress(const std::string& path) : Progress(Progress::kDefaultMax, 1.1, path) {
3833}
3834
3835Progress::Progress(int32_t initial_max, int32_t progress, float growth_factor)
3836 : Progress(initial_max, growth_factor, "") {
3837 progress_ = progress;
3838}
3839
3840Progress::Progress(int32_t initial_max, float growth_factor, const std::string& path)
3841 : initial_max_(initial_max),
3842 progress_(0),
3843 max_(initial_max),
3844 growth_factor_(growth_factor),
3845 n_runs_(0),
3846 average_max_(0),
3847 path_(path) {
3848 if (!path_.empty()) {
3849 Load();
3850 }
3851}
3852
3853void Progress::Load() {
3854 MYLOGD("Loading stats from %s\n", path_.c_str());
3855 std::string content;
3856 if (!android::base::ReadFileToString(path_, &content)) {
3857 MYLOGI("Could not read stats from %s; using max of %d\n", path_.c_str(), max_);
3858 return;
3859 }
3860 if (content.empty()) {
3861 MYLOGE("No stats (empty file) on %s; using max of %d\n", path_.c_str(), max_);
3862 return;
3863 }
3864 std::vector<std::string> lines = android::base::Split(content, "\n");
3865
3866 if (lines.size() < 1) {
3867 MYLOGE("Invalid stats on file %s: not enough lines (%d). Using max of %d\n", path_.c_str(),
3868 (int)lines.size(), max_);
3869 return;
3870 }
3871 char* ptr;
3872 n_runs_ = strtol(lines[0].c_str(), &ptr, 10);
3873 average_max_ = strtol(ptr, nullptr, 10);
3874 if (n_runs_ <= 0 || average_max_ <= 0 || n_runs_ > STATS_MAX_N_RUNS ||
3875 average_max_ > STATS_MAX_AVERAGE) {
3876 MYLOGE("Invalid stats line on file %s: %s\n", path_.c_str(), lines[0].c_str());
3877 initial_max_ = Progress::kDefaultMax;
3878 } else {
3879 initial_max_ = average_max_;
3880 }
3881 max_ = initial_max_;
3882
3883 MYLOGI("Average max progress: %d in %d runs; estimated max: %d\n", average_max_, n_runs_, max_);
3884}
3885
3886void Progress::Save() {
3887 int32_t total = n_runs_ * average_max_ + progress_;
3888 int32_t runs = n_runs_ + 1;
3889 int32_t average = floor(((float)total) / runs);
3890 MYLOGI("Saving stats (total=%d, runs=%d, average=%d) on %s\n", total, runs, average,
3891 path_.c_str());
3892 if (path_.empty()) {
3893 return;
3894 }
3895
3896 std::string content = android::base::StringPrintf("%d %d\n", runs, average);
3897 if (!android::base::WriteStringToFile(content, path_)) {
3898 MYLOGE("Could not save stats on %s\n", path_.c_str());
3899 }
3900}
3901
3902int32_t Progress::Get() const {
3903 return progress_;
3904}
3905
3906bool Progress::Inc(int32_t delta_sec) {
3907 bool changed = false;
3908 if (delta_sec >= 0) {
3909 progress_ += delta_sec;
3910 if (progress_ > max_) {
3911 int32_t old_max = max_;
3912 max_ = floor((float)progress_ * growth_factor_);
3913 MYLOGD("Adjusting max progress from %d to %d\n", old_max, max_);
3914 changed = true;
3915 }
3916 }
3917 return changed;
3918}
3919
3920int32_t Progress::GetMax() const {
3921 return max_;
3922}
3923
3924int32_t Progress::GetInitialMax() const {
3925 return initial_max_;
3926}
3927
3928void Progress::Dump(int fd, const std::string& prefix) const {
3929 const char* pr = prefix.c_str();
3930 dprintf(fd, "%sprogress: %d\n", pr, progress_);
3931 dprintf(fd, "%smax: %d\n", pr, max_);
3932 dprintf(fd, "%sinitial_max: %d\n", pr, initial_max_);
3933 dprintf(fd, "%sgrowth_factor: %0.2f\n", pr, growth_factor_);
3934 dprintf(fd, "%spath: %s\n", pr, path_.c_str());
3935 dprintf(fd, "%sn_runs: %d\n", pr, n_runs_);
3936 dprintf(fd, "%saverage_max: %d\n", pr, average_max_);
3937}
3938
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003939std::string Dumpstate::GetPath(const std::string& suffix) const {
3940 return GetPath(bugreport_internal_dir_, suffix);
3941}
3942
3943std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
3944 return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
3945 name_.c_str(), suffix.c_str());
3946}
3947
3948void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
3949 progress_ = std::move(progress);
3950}
3951
3952void for_each_userid(void (*func)(int), const char *header) {
3953 std::string title = header == nullptr ? "for_each_userid" : android::base::StringPrintf(
3954 "for_each_userid(%s)", header);
3955 DurationReporter duration_reporter(title);
3956 if (PropertiesHelper::IsDryRun()) return;
3957
3958 DIR *d;
3959 struct dirent *de;
3960
3961 if (header) printf("\n------ %s ------\n", header);
3962 func(0);
3963
3964 if (!(d = opendir("/data/system/users"))) {
3965 printf("Failed to open /data/system/users (%s)\n", strerror(errno));
3966 return;
3967 }
3968
3969 while ((de = readdir(d))) {
3970 int userid;
3971 if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
3972 continue;
3973 }
3974 func(userid);
3975 }
3976
3977 closedir(d);
3978}
3979
3980static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
3981 DIR *d;
3982 struct dirent *de;
3983
3984 if (!(d = opendir("/proc"))) {
3985 printf("Failed to open /proc (%s)\n", strerror(errno));
3986 return;
3987 }
3988
3989 if (header) printf("\n------ %s ------\n", header);
3990 while ((de = readdir(d))) {
3991 if (ds.IsUserConsentDenied()) {
3992 MYLOGE(
3993 "Returning early because user denied consent to share bugreport with calling app.");
3994 closedir(d);
3995 return;
3996 }
3997 int pid;
3998 int fd;
3999 char cmdpath[255];
4000 char cmdline[255];
4001
4002 if (!(pid = atoi(de->d_name))) {
4003 continue;
4004 }
4005
4006 memset(cmdline, 0, sizeof(cmdline));
4007
4008 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
4009 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
4010 TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
4011 close(fd);
4012 if (cmdline[0]) {
4013 helper(pid, cmdline, arg);
4014 continue;
4015 }
4016 }
4017
4018 // if no cmdline, a kernel thread has comm
4019 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
4020 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
4021 TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
4022 close(fd);
4023 if (cmdline[1]) {
4024 cmdline[0] = '[';
4025 size_t len = strcspn(cmdline, "\f\b\r\n");
4026 cmdline[len] = ']';
4027 cmdline[len+1] = '\0';
4028 }
4029 }
4030 if (!cmdline[0]) {
4031 strcpy(cmdline, "N/A");
4032 }
4033 helper(pid, cmdline, arg);
4034 }
4035
4036 closedir(d);
4037}
4038
4039static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
4040 for_each_pid_func *func = (for_each_pid_func*) arg;
4041 func(pid, cmdline);
4042}
4043
4044void for_each_pid(for_each_pid_func func, const char *header) {
4045 std::string title = header == nullptr ? "for_each_pid"
4046 : android::base::StringPrintf("for_each_pid(%s)", header);
4047 DurationReporter duration_reporter(title);
4048 if (PropertiesHelper::IsDryRun()) return;
4049
4050 __for_each_pid(for_each_pid_helper, header, (void *) func);
4051}
4052
4053static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
4054 DIR *d;
4055 struct dirent *de;
4056 char taskpath[255];
4057 for_each_tid_func *func = (for_each_tid_func *) arg;
4058
4059 snprintf(taskpath, sizeof(taskpath), "/proc/%d/task", pid);
4060
4061 if (!(d = opendir(taskpath))) {
4062 printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
4063 return;
4064 }
4065
4066 func(pid, pid, cmdline);
4067
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 tid;
4076 int fd;
4077 char commpath[255];
4078 char comm[255];
4079
4080 if (!(tid = atoi(de->d_name))) {
4081 continue;
4082 }
4083
4084 if (tid == pid)
4085 continue;
4086
4087 snprintf(commpath, sizeof(commpath), "/proc/%d/comm", tid);
4088 memset(comm, 0, sizeof(comm));
4089 if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
4090 strcpy(comm, "N/A");
4091 } else {
4092 char *c;
4093 TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
4094 close(fd);
4095
4096 c = strrchr(comm, '\n');
4097 if (c) {
4098 *c = '\0';
4099 }
4100 }
4101 func(pid, tid, comm);
4102 }
4103
4104 closedir(d);
4105}
4106
4107void for_each_tid(for_each_tid_func func, const char *header) {
4108 std::string title = header == nullptr ? "for_each_tid"
4109 : android::base::StringPrintf("for_each_tid(%s)", header);
4110 DurationReporter duration_reporter(title);
4111
4112 if (PropertiesHelper::IsDryRun()) return;
4113
4114 __for_each_pid(for_each_tid_helper, header, (void *) func);
4115}
4116
4117void show_wchan(int pid, int tid, const char *name) {
4118 if (PropertiesHelper::IsDryRun()) return;
4119
4120 char path[255];
4121 char buffer[255];
4122 int fd, ret, save_errno;
4123 char name_buffer[255];
4124
4125 memset(buffer, 0, sizeof(buffer));
4126
4127 snprintf(path, sizeof(path), "/proc/%d/wchan", tid);
4128 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
4129 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
4130 return;
4131 }
4132
4133 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
4134 save_errno = errno;
4135 close(fd);
4136
4137 if (ret < 0) {
4138 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
4139 return;
4140 }
4141
4142 snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
4143 pid == tid ? 0 : 3, "", name);
4144
4145 printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
4146
4147 return;
4148}
4149
4150// print time in centiseconds
4151static void snprcent(char *buffer, size_t len, size_t spc,
4152 unsigned long long time) {
4153 static long hz; // cache discovered hz
4154
4155 if (hz <= 0) {
4156 hz = sysconf(_SC_CLK_TCK);
4157 if (hz <= 0) {
4158 hz = 1000;
4159 }
4160 }
4161
4162 // convert to centiseconds
4163 time = (time * 100 + (hz / 2)) / hz;
4164
4165 char str[16];
4166
4167 snprintf(str, sizeof(str), " %llu.%02u",
4168 time / 100, (unsigned)(time % 100));
4169 size_t offset = strlen(buffer);
4170 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
4171 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
4172}
4173
4174// print permille as a percent
4175static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
4176 char str[16];
4177
4178 snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
4179 size_t offset = strlen(buffer);
4180 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
4181 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
4182}
4183
4184void show_showtime(int pid, const char *name) {
4185 if (PropertiesHelper::IsDryRun()) return;
4186
4187 char path[255];
4188 char buffer[1023];
4189 int fd, ret, save_errno;
4190
4191 memset(buffer, 0, sizeof(buffer));
4192
4193 snprintf(path, sizeof(path), "/proc/%d/stat", pid);
4194 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
4195 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
4196 return;
4197 }
4198
4199 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
4200 save_errno = errno;
4201 close(fd);
4202
4203 if (ret < 0) {
4204 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
4205 return;
4206 }
4207
4208 // field 14 is utime
4209 // field 15 is stime
4210 // field 42 is iotime
4211 unsigned long long utime = 0, stime = 0, iotime = 0;
4212 if (sscanf(buffer,
4213 "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
4214 "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
4215 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
4216 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
4217 &utime, &stime, &iotime) != 3) {
4218 return;
4219 }
4220
4221 unsigned long long total = utime + stime;
4222 if (!total) {
4223 return;
4224 }
4225
4226 unsigned permille = (iotime * 1000 + (total / 2)) / total;
4227 if (permille > 1000) {
4228 permille = 1000;
4229 }
4230
4231 // try to beautify and stabilize columns at <80 characters
4232 snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
4233 if ((name[0] != '[') || utime) {
4234 snprcent(buffer, sizeof(buffer), 57, utime);
4235 }
4236 snprcent(buffer, sizeof(buffer), 65, stime);
4237 if ((name[0] != '[') || iotime) {
4238 snprcent(buffer, sizeof(buffer), 73, iotime);
4239 }
4240 if (iotime) {
4241 snprdec(buffer, sizeof(buffer), 79, permille);
4242 }
4243 puts(buffer); // adds a trailing newline
4244
4245 return;
4246}
4247
4248void do_dmesg() {
4249 const char *title = "KERNEL LOG (dmesg)";
4250 DurationReporter duration_reporter(title);
4251 printf("------ %s ------\n", title);
4252
4253 if (PropertiesHelper::IsDryRun()) return;
4254
4255 /* Get size of kernel buffer */
4256 int size = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
4257 if (size <= 0) {
4258 printf("Unexpected klogctl return value: %d\n\n", size);
4259 return;
4260 }
4261 char *buf = (char *) malloc(size + 1);
4262 if (buf == nullptr) {
4263 printf("memory allocation failed\n\n");
4264 return;
4265 }
4266 int retval = klogctl(KLOG_READ_ALL, buf, size);
4267 if (retval < 0) {
4268 printf("klogctl failure\n\n");
4269 free(buf);
4270 return;
4271 }
4272 buf[retval] = '\0';
4273 printf("%s\n\n", buf);
4274 free(buf);
4275 return;
4276}
4277
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004278int Dumpstate::DumpFile(const std::string& title, const std::string& path) {
4279 DurationReporter duration_reporter(title);
4280
4281 int status = DumpFileToFd(STDOUT_FILENO, title, path);
4282
4283 UpdateProgress(WEIGHT_FILE);
4284
4285 return status;
4286}
4287
4288int read_file_as_long(const char *path, long int *output) {
luoqiangwei15fcf2022024-03-07 15:29:20 +08004289 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
4290 if (fd.get() < 0) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004291 int err = errno;
4292 MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
4293 return -1;
4294 }
4295 char buffer[50];
luoqiangwei15fcf2022024-03-07 15:29:20 +08004296 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer, sizeof(buffer)));
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004297 if (bytes_read == -1) {
4298 MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
4299 return -2;
4300 }
4301 if (bytes_read == 0) {
4302 MYLOGE("File %s is empty\n", path);
4303 return -3;
4304 }
4305 *output = atoi(buffer);
4306 return 0;
4307}
4308
4309/* calls skip to gate calling dump_from_fd recursively
4310 * in the specified directory. dump_from_fd defaults to
4311 * dump_file_from_fd above when set to NULL. skip defaults
4312 * to false when set to NULL. dump_from_fd will always be
4313 * called with title NULL.
4314 */
4315int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
4316 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4317 DurationReporter duration_reporter(title);
4318 DIR *dirp;
4319 struct dirent *d;
4320 char *newpath = nullptr;
4321 const char *slash = "/";
4322 int retval = 0;
4323
4324 if (!title.empty()) {
4325 printf("------ %s (%s) ------\n", title.c_str(), dir);
4326 }
4327 if (PropertiesHelper::IsDryRun()) return 0;
4328
4329 if (dir[strlen(dir) - 1] == '/') {
4330 ++slash;
4331 }
4332 dirp = opendir(dir);
4333 if (dirp == nullptr) {
4334 retval = -errno;
4335 MYLOGE("%s: %s\n", dir, strerror(errno));
4336 return retval;
4337 }
4338
4339 if (!dump_from_fd) {
4340 dump_from_fd = dump_file_from_fd;
4341 }
4342 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4343 if ((d->d_name[0] == '.')
4344 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4345 || (d->d_name[1] == '\0'))) {
4346 continue;
4347 }
4348 asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
4349 (d->d_type == DT_DIR) ? "/" : "");
4350 if (!newpath) {
4351 retval = -errno;
4352 continue;
4353 }
4354 if (skip && (*skip)(newpath)) {
4355 continue;
4356 }
4357 if (d->d_type == DT_DIR) {
4358 int ret = dump_files("", newpath, skip, dump_from_fd);
4359 if (ret < 0) {
4360 retval = ret;
4361 }
4362 continue;
4363 }
4364 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
4365 if (fd.get() < 0) {
4366 retval = -1;
4367 printf("*** %s: %s\n", newpath, strerror(errno));
4368 continue;
4369 }
4370 (*dump_from_fd)(nullptr, newpath, fd.get());
4371 }
4372 closedir(dirp);
4373 if (!title.empty()) {
4374 printf("\n");
4375 }
4376 return retval;
4377}
4378
4379/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
4380 * it's possible to avoid issues where opening the file itself can get
4381 * stuck.
4382 */
4383int dump_file_from_fd(const char *title, const char *path, int fd) {
4384 if (PropertiesHelper::IsDryRun()) return 0;
4385
4386 int flags = fcntl(fd, F_GETFL);
4387 if (flags == -1) {
4388 printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
4389 return -1;
4390 } else if (!(flags & O_NONBLOCK)) {
4391 printf("*** %s: fd must have O_NONBLOCK set.\n", path);
4392 return -1;
4393 }
4394 return DumpFileFromFdToFd(title, path, fd, STDOUT_FILENO, PropertiesHelper::IsDryRun());
4395}
4396
4397int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004398 const CommandOptions& options, bool verbose_duration, int out_fd) {
4399 DurationReporter duration_reporter(title, false /* logcat_only */,
4400 verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004401
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004402 int status = RunCommandToFd(out_fd, title, full_command, options);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004403
4404 /* TODO: for now we're simplifying the progress calculation by using the
4405 * timeout as the weight. It's a good approximation for most cases, except when calling dumpsys,
4406 * where its weight should be much higher proportionally to its timeout.
4407 * Ideally, it should use a options.EstimatedDuration() instead...*/
4408 UpdateProgress(options.Timeout());
4409
4410 return status;
4411}
4412
4413void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
Rhed Jaoe017f982020-07-21 17:58:41 +08004414 const CommandOptions& options, long dumpsysTimeoutMs, int out_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004415 long timeout_ms = dumpsysTimeoutMs > 0 ? dumpsysTimeoutMs : options.TimeoutInMs();
4416 std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-T", std::to_string(timeout_ms)};
4417 dumpsys.insert(dumpsys.end(), dumpsys_args.begin(), dumpsys_args.end());
Rhed Jaoe017f982020-07-21 17:58:41 +08004418 RunCommand(title, dumpsys, options, false, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004419}
4420
Dieter Hsu105ad0c2020-09-29 15:23:33 +08004421static int open_socket(const char* service) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004422 int s = android_get_control_socket(service);
4423 if (s < 0) {
4424 MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
4425 return -1;
4426 }
4427 fcntl(s, F_SETFD, FD_CLOEXEC);
4428
4429 // Set backlog to 0 to make sure that queue size will be minimum.
4430 // In Linux, because the minimum queue will be 1, connect() will be blocked
4431 // if the other clients already called connect() and the connection request was not accepted.
4432 if (listen(s, 0) < 0) {
4433 MYLOGE("listen(control socket): %s\n", strerror(errno));
4434 return -1;
4435 }
4436
4437 struct sockaddr addr;
4438 socklen_t alen = sizeof(addr);
Abhijeet Kaur2113cae2019-09-13 09:24:15 +01004439 int fd = accept4(s, &addr, &alen, SOCK_CLOEXEC);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004440
4441 // Close socket just after accept(), to make sure that connect() by client will get error
4442 // when the socket is used by the other services.
4443 // There is still a race condition possibility between accept and close, but there is no way
4444 // to close-on-accept atomically.
4445 // See detail; b/123306389#comment25
4446 close(s);
4447
4448 if (fd < 0) {
4449 MYLOGE("accept(control socket): %s\n", strerror(errno));
4450 return -1;
4451 }
4452
4453 return fd;
4454}
4455
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004456// TODO: should call is_valid_output_file and/or be merged into it.
4457void create_parent_dirs(const char *path) {
4458 char *chp = const_cast<char *> (path);
4459
4460 /* skip initial slash */
4461 if (chp[0] == '/')
4462 chp++;
4463
4464 /* create leading directories, if necessary */
4465 struct stat dir_stat;
4466 while (chp && chp[0]) {
4467 chp = strchr(chp, '/');
4468 if (chp) {
4469 *chp = 0;
4470 if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
4471 MYLOGI("Creating directory %s\n", path);
4472 if (mkdir(path, 0770)) { /* drwxrwx--- */
4473 MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
4474 } else if (chown(path, AID_SHELL, AID_SHELL)) {
4475 MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
4476 }
4477 }
4478 *chp++ = '/';
4479 }
4480 }
4481}
4482
4483bool _redirect_to_file(FILE* redirect, char* path, int truncate_flag) {
4484 create_parent_dirs(path);
4485
4486 int fd = TEMP_FAILURE_RETRY(open(path,
4487 O_WRONLY | O_CREAT | truncate_flag | O_CLOEXEC | O_NOFOLLOW,
4488 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
4489 if (fd < 0) {
4490 MYLOGE("%s: %s\n", path, strerror(errno));
4491 return false;
4492 }
4493
4494 TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
4495 close(fd);
4496 return true;
4497}
4498
4499bool redirect_to_file(FILE* redirect, char* path) {
4500 return _redirect_to_file(redirect, path, O_TRUNC);
4501}
4502
4503bool redirect_to_existing_file(FILE* redirect, char* path) {
4504 return _redirect_to_file(redirect, path, O_APPEND);
4505}
4506
4507void dump_route_tables() {
4508 DurationReporter duration_reporter("DUMP ROUTE TABLES");
4509 if (PropertiesHelper::IsDryRun()) return;
4510 const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
4511 ds.DumpFile("RT_TABLES", RT_TABLES_PATH);
4512 FILE* fp = fopen(RT_TABLES_PATH, "re");
4513 if (!fp) {
4514 printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
4515 return;
4516 }
4517 char table[16];
4518 // Each line has an integer (the table number), a space, and a string (the table name). We only
4519 // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
4520 // Add a fixed max limit so this doesn't go awry.
4521 for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
4522 RunCommand("ROUTE TABLE IPv4", {"ip", "-4", "route", "show", "table", table});
4523 RunCommand("ROUTE TABLE IPv6", {"ip", "-6", "route", "show", "table", table});
4524 }
4525 fclose(fp);
4526}
4527
Li Li830179f2022-01-04 12:53:29 -08004528void dump_frozen_cgroupfs(const char *dir, int level,
4529 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4530 DIR *dirp;
4531 struct dirent *d;
4532 char *newpath = nullptr;
4533
4534 dirp = opendir(dir);
4535 if (dirp == nullptr) {
4536 MYLOGE("%s: %s\n", dir, strerror(errno));
4537 return;
4538 }
4539
4540 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4541 if ((d->d_name[0] == '.')
4542 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4543 || (d->d_name[1] == '\0'))) {
4544 continue;
4545 }
4546 if (d->d_type == DT_DIR) {
4547 asprintf(&newpath, "%s/%s/", dir, d->d_name);
4548 if (!newpath) {
4549 continue;
4550 }
4551 if (level == 0 && !strncmp(d->d_name, "uid_", 4)) {
4552 dump_frozen_cgroupfs(newpath, 1, dump_from_fd);
4553 } else if (level == 1 && !strncmp(d->d_name, "pid_", 4)) {
4554 char *freezer = nullptr;
4555 asprintf(&freezer, "%s/%s", newpath, "cgroup.freeze");
4556 if (freezer) {
4557 FILE* fp = fopen(freezer, "r");
4558 if (fp != NULL) {
4559 int frozen;
4560 fscanf(fp, "%d", &frozen);
4561 if (frozen > 0) {
4562 dump_files("", newpath, skip_none, dump_from_fd);
4563 }
4564 fclose(fp);
4565 }
4566 free(freezer);
4567 }
4568 }
4569 }
4570 }
4571 closedir(dirp);
4572}
4573
4574void dump_frozen_cgroupfs() {
Li Li830179f2022-01-04 12:53:29 -08004575 MYLOGD("Adding frozen processes from %s\n", CGROUPFS_DIR);
4576 DurationReporter duration_reporter("FROZEN CGROUPFS");
4577 if (PropertiesHelper::IsDryRun()) return;
4578 dump_frozen_cgroupfs(CGROUPFS_DIR, 0, _add_file_from_fd);
4579}
4580
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004581void Dumpstate::UpdateProgress(int32_t delta_sec) {
4582 if (progress_ == nullptr) {
4583 MYLOGE("UpdateProgress: progress_ not set\n");
4584 return;
4585 }
Rhed Jaobf63d8a2020-07-21 15:42:55 +08004586 // This function updates progress related members of the dumpstate and reports
4587 // progress percentage to the bugreport client. Since it could be called by
4588 // different dump tasks at the same time if the parallel run is enabled, a
4589 // mutex lock is necessary here to synchronize the call.
4590 std::lock_guard<std::recursive_mutex> lock(mutex_);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004591
4592 // Always update progess so stats can be tuned...
Nandana Dutt402a8392019-06-14 14:25:13 +01004593 progress_->Inc(delta_sec);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004594
4595 // ...but only notifiy listeners when necessary.
4596 if (!options_->do_progress_updates) return;
4597
4598 int progress = progress_->Get();
4599 int max = progress_->GetMax();
Nandana Dutt402a8392019-06-14 14:25:13 +01004600 int percent = 100 * progress / max;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004601
Nandana Dutt402a8392019-06-14 14:25:13 +01004602 if (last_reported_percent_progress_ > 0 && percent <= last_reported_percent_progress_) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004603 return;
4604 }
Nandana Dutt402a8392019-06-14 14:25:13 +01004605 last_reported_percent_progress_ = percent;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004606
4607 if (control_socket_fd_ >= 0) {
4608 dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
4609 fsync(control_socket_fd_);
4610 }
4611
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004612 if (listener_ != nullptr) {
Nandana Dutt235c6672019-11-14 15:22:32 +00004613 if (percent % 10 == 0) {
4614 // We don't want to spam logcat, so only log multiples of 10.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004615 MYLOGD("Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004616 } else {
4617 // stderr is ignored on normal invocations, but useful when calling
4618 // /system/bin/dumpstate directly for debuggging.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004619 fprintf(stderr, "Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004620 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004621
4622 listener_->onProgress(percent);
4623 }
4624}
4625
4626void Dumpstate::TakeScreenshot(const std::string& path) {
4627 const std::string& real_path = path.empty() ? screenshot_path_ : path;
4628 int status =
4629 RunCommand("", {"/system/bin/screencap", "-p", real_path},
4630 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
4631 if (status == 0) {
4632 MYLOGD("Screenshot saved on %s\n", real_path.c_str());
4633 } else {
4634 MYLOGE("Failed to take screenshot on %s\n", real_path.c_str());
4635 }
Paul Chang0d2aad72020-02-13 20:04:03 +08004636 if (listener_ != nullptr) {
4637 // Show a visual indication to indicate screenshot is taken via
4638 // IDumpstateListener.onScreenshotTaken()
4639 listener_->onScreenshotTaken(status == 0);
4640 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004641}
4642
4643bool is_dir(const char* pathname) {
4644 struct stat info;
4645 if (stat(pathname, &info) == -1) {
4646 return false;
4647 }
4648 return S_ISDIR(info.st_mode);
4649}
4650
4651time_t get_mtime(int fd, time_t default_mtime) {
4652 struct stat info;
4653 if (fstat(fd, &info) == -1) {
4654 return default_mtime;
4655 }
4656 return info.st_mtime;
4657}