blob: d5125f01d6aefd462e78fe5e4f06a962072aed86 [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"
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700194
Narayan Kamath8f788292017-05-25 13:20:39 +0100195// TODO(narayan): Since this information has to be kept in sync
196// with tombstoned, we should just put it in a common header.
197//
198// File: system/core/debuggerd/tombstoned/tombstoned.cpp
Narayan Kamathbd863722017-06-01 18:50:12 +0100199static const std::string TOMBSTONE_DIR = "/data/tombstones/";
200static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
201static const std::string ANR_DIR = "/data/anr/";
202static const std::string ANR_FILE_PREFIX = "anr_";
Andy Hungd62f7e62024-01-11 15:47:52 -0800203static const std::string ANR_TRACE_FILE_PREFIX = "trace_";
Woody Lin20767a92022-11-29 15:50:24 +0800204static const std::string SHUTDOWN_CHECKPOINTS_DIR = "/data/system/shutdown-checkpoints/";
205static const std::string SHUTDOWN_CHECKPOINTS_FILE_PREFIX = "checkpoints-";
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700206
Felipe Lemee844a9d2016-09-21 15:01:39 -0700207// TODO: temporary variables and functions used during C++ refactoring
Nandana Dutt979388e2018-11-30 16:48:55 +0000208
Nandana Dutt5c390032019-03-12 10:52:56 +0000209#define RETURN_IF_USER_DENIED_CONSENT() \
210 if (ds.IsUserConsentDenied()) { \
211 MYLOGE("Returning early as user denied consent to share bugreport with calling app."); \
212 return Dumpstate::RunStatus::USER_CONSENT_DENIED; \
213 }
214
215// Runs func_ptr, but checks user consent before and after running it. Returns USER_CONSENT_DENIED
216// if consent is found to be denied.
217#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(func_ptr, ...) \
218 RETURN_IF_USER_DENIED_CONSENT(); \
219 func_ptr(__VA_ARGS__); \
220 RETURN_IF_USER_DENIED_CONSENT();
221
Rhed Jao5377d792020-07-16 17:37:39 +0800222// Runs func_ptr, and logs a duration report after it's finished.
223#define RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, ...) \
224 { \
225 DurationReporter duration_reporter_in_macro(log_title); \
226 func_ptr(__VA_ARGS__); \
227 }
228
229// Similar with RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK, an additional duration report
230// is output after a slow function is finished.
231#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(log_title, func_ptr, ...) \
232 RETURN_IF_USER_DENIED_CONSENT(); \
233 RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, __VA_ARGS__); \
234 RETURN_IF_USER_DENIED_CONSENT();
235
Chris Morinbc223142022-02-04 14:17:11 -0800236#define WAIT_TASK_WITH_CONSENT_CHECK(future) \
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800237 RETURN_IF_USER_DENIED_CONSENT(); \
Chris Morinbc223142022-02-04 14:17:11 -0800238 WaitForTask(future); \
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800239 RETURN_IF_USER_DENIED_CONSENT();
240
Sahana Raof35ed432019-07-12 10:47:52 +0100241static const char* WAKE_LOCK_NAME = "dumpstate_wakelock";
242
Rhed Jao5377d792020-07-16 17:37:39 +0800243// Names of parallel tasks, they are used for the DumpPool to identify the dump
244// task and the log title of the duration report.
245static const std::string DUMP_TRACES_TASK = "DUMP TRACES";
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800246static const std::string DUMP_INCIDENT_REPORT_TASK = "INCIDENT REPORT";
Aaron Huang24d215d2022-04-27 18:51:16 +0800247static const std::string DUMP_NETSTATS_PROTO_TASK = "DUMP NETSTATS PROTO";
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800248static const std::string DUMP_HALS_TASK = "DUMP HALS";
249static const std::string DUMP_BOARD_TASK = "dumpstate_board()";
Rhed Jaoe017f982020-07-21 17:58:41 +0800250static const std::string DUMP_CHECKINS_TASK = "DUMP CHECKINS";
Kean Mariottica20f2d2023-12-15 09:34:25 +0000251static const std::string SERIALIZE_PERFETTO_TRACE_TASK = "SERIALIZE PERFETTO TRACE";
Rhed Jao5377d792020-07-16 17:37:39 +0800252
Nandana Dutt979388e2018-11-30 16:48:55 +0000253namespace android {
254namespace os {
255namespace {
256
257static int Open(std::string path, int flags, mode_t mode = 0) {
258 int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
259 if (fd == -1) {
260 MYLOGE("open(%s, %s)\n", path.c_str(), strerror(errno));
261 }
262 return fd;
263}
264
mhasank2d75c442020-06-11 15:05:25 -0700265static int OpenForWrite(std::string path) {
266 return Open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
267 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
268}
Nandana Dutt979388e2018-11-30 16:48:55 +0000269
270static int OpenForRead(std::string path) {
271 return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
272}
273
274bool CopyFile(int in_fd, int out_fd) {
275 char buf[4096];
276 ssize_t byte_count;
277 while ((byte_count = TEMP_FAILURE_RETRY(read(in_fd, buf, sizeof(buf)))) > 0) {
278 if (!android::base::WriteFully(out_fd, buf, byte_count)) {
279 return false;
280 }
281 }
282 return (byte_count != -1);
283}
284
285static bool CopyFileToFd(const std::string& input_file, int out_fd) {
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000286 MYLOGD("Going to copy file (%s) to %d\n", input_file.c_str(), out_fd);
Nandana Dutt979388e2018-11-30 16:48:55 +0000287
288 // Obtain a handle to the source file.
289 android::base::unique_fd in_fd(OpenForRead(input_file));
290 if (out_fd != -1 && in_fd.get() != -1) {
291 if (CopyFile(in_fd.get(), out_fd)) {
292 return true;
293 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000294 MYLOGE("Failed to copy file: %s\n", strerror(errno));
Nandana Dutt979388e2018-11-30 16:48:55 +0000295 }
296 return false;
297}
298
Nandana Duttd2f5f082019-01-18 17:13:52 +0000299static bool UnlinkAndLogOnError(const std::string& file) {
Nandana Dutt8ae16e62020-03-27 10:20:22 +0000300 if (file.empty()) {
301 return false;
302 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000303 if (unlink(file.c_str())) {
304 MYLOGE("Failed to unlink file (%s): %s\n", file.c_str(), strerror(errno));
Nandana Duttd2f5f082019-01-18 17:13:52 +0000305 return false;
306 }
307 return true;
308}
Nandana Dutt979388e2018-11-30 16:48:55 +0000309
Nikita Ioffea325a572019-05-16 19:49:47 +0100310int64_t GetModuleMetadataVersion() {
311 auto binder = defaultServiceManager()->getService(android::String16("package_native"));
312 if (binder == nullptr) {
313 MYLOGE("Failed to retrieve package_native service");
314 return 0L;
315 }
316 auto package_service = android::interface_cast<content::pm::IPackageManagerNative>(binder);
317 std::string package_name;
318 auto status = package_service->getModuleMetadataPackageName(&package_name);
319 if (!status.isOk()) {
320 MYLOGE("Failed to retrieve module metadata package name: %s", status.toString8().c_str());
321 return 0L;
322 }
Nandana Duttdb379fa2019-10-09 16:54:41 +0100323 MYLOGD("Module metadata package name: %s\n", package_name.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100324 int64_t version_code;
325 status = package_service->getVersionCodeForPackage(android::String16(package_name.c_str()),
326 &version_code);
327 if (!status.isOk()) {
328 MYLOGE("Failed to retrieve module metadata version: %s", status.toString8().c_str());
329 return 0L;
330 }
331 return version_code;
332}
333
mhasank2d75c442020-06-11 15:05:25 -0700334static bool PathExists(const std::string& path) {
335 struct stat sb;
336 return stat(path.c_str(), &sb) == 0;
337}
338
339static bool CopyFileToFile(const std::string& input_file, const std::string& output_file) {
340 if (input_file == output_file) {
341 MYLOGD("Skipping copying bugreport file since the destination is the same (%s)\n",
342 output_file.c_str());
343 return false;
344 }
345 else if (PathExists(output_file)) {
346 MYLOGD("Cannot overwrite an existing file (%s)\n", output_file.c_str());
347 return false;
348 }
349
350 MYLOGD("Going to copy bugreport file (%s) to %s\n", input_file.c_str(), output_file.c_str());
351 android::base::unique_fd out_fd(OpenForWrite(output_file));
352 return CopyFileToFd(input_file, out_fd.get());
353}
354
Nandana Dutt979388e2018-11-30 16:48:55 +0000355} // namespace
356} // namespace os
357} // namespace android
358
Felipe Leme678727a2016-09-21 17:22:11 -0700359static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
Felipe Lemebda15a02016-11-16 17:48:25 -0800360 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
Rhed Jaoe017f982020-07-21 17:58:41 +0800361 long dumpsysTimeoutMs = 0, int out_fd = STDOUT_FILENO) {
362 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs, out_fd);
363}
364static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
365 int out_fd) {
366 return ds.RunDumpsys(title, dumpsysArgs, Dumpstate::DEFAULT_DUMPSYS, 0, out_fd);
Felipe Leme678727a2016-09-21 17:22:11 -0700367}
368static int DumpFile(const std::string& title, const std::string& path) {
369 return ds.DumpFile(title, path);
370}
Felipe Lemee82a27d2016-01-05 13:35:44 -0800371
Felipe Lemee844a9d2016-09-21 15:01:39 -0700372// Relative directory (inside the zip) for all files copied as-is into the bugreport.
373static const std::string ZIP_ROOT_DIR = "FS";
374
Vishnu Naire97d6122018-01-18 13:58:56 -0800375static const std::string kProtoPath = "proto/";
376static const std::string kProtoExt = ".proto";
Jie Song9fbfad02017-06-20 16:29:42 -0700377static const std::string kDumpstateBoardFiles[] = {
378 "dumpstate_board.txt",
Felipe Leme95d6ca52017-08-01 16:35:56 -0700379 "dumpstate_board.bin"
Jie Song9fbfad02017-06-20 16:29:42 -0700380};
381static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
382
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700383static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Lemed071c682016-10-20 16:48:00 -0700384static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700385
Felipe Lemef0292972016-11-22 13:57:05 -0800386static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
387
Narayan Kamath8f788292017-05-25 13:20:39 +0100388/*
Narayan Kamathbd863722017-06-01 18:50:12 +0100389 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
Rhed Jao01dc0c62020-06-03 17:13:30 +0800390 * The returned vector is sorted by the mtimes of the dumps with descending
Chris Morinc2cba7a2022-02-01 17:06:50 -0800391 * order.
Narayan Kamath8f788292017-05-25 13:20:39 +0100392 */
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700393static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
Chris Morinc2cba7a2022-02-01 17:06:50 -0800394 const std::string& file_prefix) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100395 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100396
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700397 if (dump_dir == nullptr) {
398 MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno));
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700399 return std::vector<DumpData>();
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700400 }
401
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700402 std::vector<DumpData> dump_data;
Narayan Kamathbd863722017-06-01 18:50:12 +0100403 struct dirent* entry = nullptr;
404 while ((entry = readdir(dump_dir.get()))) {
405 if (entry->d_type != DT_REG) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100406 continue;
407 }
408
Narayan Kamathbd863722017-06-01 18:50:12 +0100409 const std::string base_name(entry->d_name);
410 if (base_name.find(file_prefix) != 0) {
411 continue;
412 }
413
414 const std::string abs_path = dir_path + base_name;
415 android::base::unique_fd fd(
416 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
417 if (fd == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700418 MYLOGW("Unable to open dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamathbd863722017-06-01 18:50:12 +0100419 break;
420 }
421
422 struct stat st = {};
423 if (fstat(fd, &st) == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700424 MYLOGW("Unable to stat dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamath8f788292017-05-25 13:20:39 +0100425 continue;
426 }
427
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700428 dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700429 }
Rhed Jao01dc0c62020-06-03 17:13:30 +0800430 if (!dump_data.empty()) {
431 std::sort(dump_data.begin(), dump_data.end(),
432 [](const auto& a, const auto& b) { return a.mtime > b.mtime; });
433 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100434
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700435 return dump_data;
Narayan Kamath8f788292017-05-25 13:20:39 +0100436}
437
Narayan Kamathbd863722017-06-01 18:50:12 +0100438static bool AddDumps(const std::vector<DumpData>::const_iterator start,
439 const std::vector<DumpData>::const_iterator end,
440 const char* type_name, const bool add_to_zip) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100441 bool dumped = false;
Narayan Kamathbd863722017-06-01 18:50:12 +0100442 for (auto it = start; it != end; ++it) {
443 const std::string& name = it->name;
444 const int fd = it->fd;
Narayan Kamath8f788292017-05-25 13:20:39 +0100445 dumped = true;
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100446
447 // Seek to the beginning of the file before dumping any data. A given
448 // DumpData entry might be dumped multiple times in the report.
449 //
450 // For example, the most recent ANR entry is dumped to the body of the
451 // main entry and it also shows up as a separate entry in the bugreport
452 // ZIP file.
453 if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) {
454 MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(),
455 strerror(errno));
456 }
457
Chris Morinc2cba7a2022-02-01 17:06:50 -0800458 if (add_to_zip) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800459 if (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd, /* timeout = */ 0ms) != OK) {
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100460 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100461 }
462 } else {
463 dump_file_from_fd(type_name, name.c_str(), fd);
464 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100465 }
466
467 return dumped;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700468}
469
Felipe Leme635ca312016-01-05 14:23:02 -0800470// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700471void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800472 char path[PATH_MAX];
473
474 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
475 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700476 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800477 char linkname[PATH_MAX];
478 ssize_t r = readlink(path, linkname, PATH_MAX);
479 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800480 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800481 return;
482 }
483 linkname[r] = '\0';
484
485 if (mount_points.find(linkname) == mount_points.end()) {
486 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700487 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700488 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
Felipe Leme635ca312016-01-05 14:23:02 -0800489 mount_points.insert(linkname);
490 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800491 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800492 }
493 }
494}
495
496void add_mountinfo() {
Felipe Leme678727a2016-09-21 17:22:11 -0700497 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800498 mount_points.clear();
Felipe Leme46b85da2016-11-21 17:40:45 -0800499 DurationReporter duration_reporter(title, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700500 for_each_pid(do_mountinfo, nullptr);
501 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800502}
503
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700504static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
505{
506 DIR *d;
507 struct dirent *de;
508 char path[PATH_MAX];
509
510 d = opendir(driverpath);
Yi Kong19d5c002018-07-20 13:39:55 -0700511 if (d == nullptr) {
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700512 return;
513 }
514
515 while ((de = readdir(d))) {
516 if (de->d_type != DT_LNK) {
517 continue;
518 }
519 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700520 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700521 }
522
523 closedir(d);
524}
525
Mark Salyzyn326842f2015-04-30 09:49:41 -0700526static bool skip_not_stat(const char *path) {
527 static const char stat[] = "/stat";
528 size_t len = strlen(path);
529 if (path[len - 1] == '/') { /* Directory? */
530 return false;
531 }
532 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
533}
534
Jeff Sharkey9df29d52023-02-06 14:26:30 -0700535static bool skip_wtf_strictmode(const char *path) {
536 if (strstr(path, "_wtf")) {
537 return true;
538 } else if (strstr(path, "_strictmode")) {
539 return true;
540 }
541 return false;
542}
543
Felipe Leme4c2d6632016-09-28 14:32:00 -0700544static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800545 return false;
546}
547
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700548unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700549
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800550//
551// stat offsets
552// Name units description
553// ---- ----- -----------
554// read I/Os requests number of read I/Os processed
555#define __STAT_READ_IOS 0
556// read merges requests number of read I/Os merged with in-queue I/O
557#define __STAT_READ_MERGES 1
558// read sectors sectors number of sectors read
559#define __STAT_READ_SECTORS 2
560// read ticks milliseconds total wait time for read requests
561#define __STAT_READ_TICKS 3
562// write I/Os requests number of write I/Os processed
563#define __STAT_WRITE_IOS 4
564// write merges requests number of write I/Os merged with in-queue I/O
565#define __STAT_WRITE_MERGES 5
566// write sectors sectors number of sectors written
567#define __STAT_WRITE_SECTORS 6
568// write ticks milliseconds total wait time for write requests
569#define __STAT_WRITE_TICKS 7
570// in_flight requests number of I/Os currently in flight
571#define __STAT_IN_FLIGHT 8
572// io_ticks milliseconds total time this block device has been active
573#define __STAT_IO_TICKS 9
574// time_in_queue milliseconds total wait time for all requests
575#define __STAT_IN_QUEUE 10
576#define __STAT_NUMBER_FIELD 11
577//
578// read I/Os, write I/Os
579// =====================
580//
581// These values increment when an I/O request completes.
582//
583// read merges, write merges
584// =========================
585//
586// These values increment when an I/O request is merged with an
587// already-queued I/O request.
588//
589// read sectors, write sectors
590// ===========================
591//
592// These values count the number of sectors read from or written to this
593// block device. The "sectors" in question are the standard UNIX 512-byte
594// sectors, not any device- or filesystem-specific block size. The
595// counters are incremented when the I/O completes.
596#define SECTOR_SIZE 512
597//
598// read ticks, write ticks
599// =======================
600//
601// These values count the number of milliseconds that I/O requests have
602// waited on this block device. If there are multiple I/O requests waiting,
603// these values will increase at a rate greater than 1000/second; for
604// example, if 60 read requests wait for an average of 30 ms, the read_ticks
605// field will increase by 60*30 = 1800.
606//
607// in_flight
608// =========
609//
610// This value counts the number of I/O requests that have been issued to
611// the device driver but have not yet completed. It does not include I/O
612// requests that are in the queue but not yet issued to the device driver.
613//
614// io_ticks
615// ========
616//
617// This value counts the number of milliseconds during which the device has
618// had I/O requests queued.
619//
620// time_in_queue
621// =============
622//
623// This value counts the number of milliseconds that I/O requests have waited
624// on this block device. If there are multiple I/O requests waiting, this
625// value will increase as the product of the number of milliseconds times the
626// number of requests waiting (see "read ticks" above for an example).
627#define S_TO_MS 1000
628//
629
Mark Salyzyn326842f2015-04-30 09:49:41 -0700630static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800631 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700632 bool z;
Yi Kong19d5c002018-07-20 13:39:55 -0700633 char *cp, *buffer = nullptr;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700634 size_t i = 0;
Josh Gao7c4258c2018-06-25 13:40:08 -0700635 FILE *fp = fdopen(dup(fd), "rb");
Mark Salyzyn326842f2015-04-30 09:49:41 -0700636 getline(&buffer, &i, fp);
637 fclose(fp);
638 if (!buffer) {
639 return -errno;
640 }
641 i = strlen(buffer);
642 while ((i > 0) && (buffer[i - 1] == '\n')) {
643 buffer[--i] = '\0';
644 }
645 if (!*buffer) {
646 free(buffer);
647 return 0;
648 }
649 z = true;
650 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800651 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700652 if (fields[i] != 0) {
653 z = false;
654 }
655 }
656 if (z) { /* never accessed */
657 free(buffer);
658 return 0;
659 }
660
Wei Wang509bb5d2017-06-09 14:42:12 -0700661 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
662 path += sizeof(BLK_DEV_SYS_DIR) - 1;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700663 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700664
665 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
666 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
667 "W-wait", "in-fli", "activ", "T-wait", path, buffer);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700668 free(buffer);
669
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800670 if (fields[__STAT_IO_TICKS]) {
671 unsigned long read_perf = 0;
672 unsigned long read_ios = 0;
673 if (fields[__STAT_READ_TICKS]) {
674 unsigned long long divisor = fields[__STAT_READ_TICKS]
675 * fields[__STAT_IO_TICKS];
676 read_perf = ((unsigned long long)SECTOR_SIZE
677 * fields[__STAT_READ_SECTORS]
678 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
679 / divisor;
680 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
681 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
682 / divisor;
683 }
684
685 unsigned long write_perf = 0;
686 unsigned long write_ios = 0;
687 if (fields[__STAT_WRITE_TICKS]) {
688 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
689 * fields[__STAT_IO_TICKS];
690 write_perf = ((unsigned long long)SECTOR_SIZE
691 * fields[__STAT_WRITE_SECTORS]
692 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
693 / divisor;
694 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
695 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
696 / divisor;
697 }
698
699 unsigned queue = (fields[__STAT_IN_QUEUE]
700 + (fields[__STAT_IO_TICKS] >> 1))
701 / fields[__STAT_IO_TICKS];
702
703 if (!write_perf && !write_ios) {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700704 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 -0800705 } else {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700706 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 -0800707 read_ios, write_perf, write_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800708 }
709
710 /* bugreport timeout factor adjustment */
711 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
712 worst_write_perf = write_perf;
713 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700714 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700715 return 0;
716}
717
Yao Chenbe3bbc12018-01-17 16:31:10 -0800718static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
719
Tom Cherryf4472f32020-08-05 09:31:17 -0700720// Returns the actual readable size of the given buffer or -1 on error.
721static long logcat_buffer_readable_size(const std::string& buffer) {
722 std::unique_ptr<logger_list, decltype(&android_logger_list_free)> logger_list{
723 android_logger_list_alloc(0, 0, 0), &android_logger_list_free};
724 auto logger = android_logger_open(logger_list.get(), android_name_to_log_id(buffer.c_str()));
725
726 return android_logger_get_log_readable_size(logger);
727}
728
729// Returns timeout in ms to read a list of buffers.
Yao Chenbe3bbc12018-01-17 16:31:10 -0800730static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
731 unsigned long timeout_ms = 0;
732 for (const auto& buffer : buffers) {
Tom Cherryf4472f32020-08-05 09:31:17 -0700733 long readable_size = logcat_buffer_readable_size(buffer);
734 if (readable_size > 0) {
735 // Engineering margin is ten-fold our guess.
736 timeout_ms += 10 * (readable_size + worst_write_perf) / worst_write_perf;
737 }
Yao Chenbe3bbc12018-01-17 16:31:10 -0800738 }
739 return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700740}
741
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800742// Opens a socket and returns its file descriptor.
743static int open_socket(const char* service);
744
Nandana Duttd2f5f082019-01-18 17:13:52 +0000745Dumpstate::ConsentCallback::ConsentCallback() : result_(UNAVAILABLE), start_time_(Nanotime()) {
746}
747
748android::binder::Status Dumpstate::ConsentCallback::onReportApproved() {
749 std::lock_guard<std::mutex> lock(lock_);
750 result_ = APPROVED;
751 MYLOGD("User approved consent to share bugreport\n");
Paul Chang0d2aad72020-02-13 20:04:03 +0800752
753 // Maybe copy screenshot so calling app can display the screenshot to the user as soon as
754 // consent is granted.
755 if (ds.options_->is_screenshot_copied) {
756 return android::binder::Status::ok();
757 }
758
759 if (!ds.options_->do_screenshot || ds.options_->screenshot_fd.get() == -1 ||
760 !ds.do_early_screenshot_) {
761 return android::binder::Status::ok();
762 }
763
764 bool copy_succeeded = android::os::CopyFileToFd(ds.screenshot_path_,
765 ds.options_->screenshot_fd.get());
766 ds.options_->is_screenshot_copied = copy_succeeded;
767 if (copy_succeeded) {
768 android::os::UnlinkAndLogOnError(ds.screenshot_path_);
769 }
Nandana Duttd2f5f082019-01-18 17:13:52 +0000770 return android::binder::Status::ok();
771}
772
773android::binder::Status Dumpstate::ConsentCallback::onReportDenied() {
774 std::lock_guard<std::mutex> lock(lock_);
775 result_ = DENIED;
776 MYLOGW("User denied consent to share bugreport\n");
777 return android::binder::Status::ok();
778}
779
780UserConsentResult Dumpstate::ConsentCallback::getResult() {
781 std::lock_guard<std::mutex> lock(lock_);
782 return result_;
783}
784
785uint64_t Dumpstate::ConsentCallback::getElapsedTimeMs() const {
Hunter Knepshieldf0a39052020-01-03 14:53:04 -0800786 return (Nanotime() - start_time_) / NANOS_PER_MILLI;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000787}
788
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700789void Dumpstate::PrintHeader() const {
MÃ¥rten Kongstad60195a72022-09-20 14:14:20 +0200790 std::string build, fingerprint, radio, bootloader, network, sdkversion;
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700791 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700792
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700793 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
794 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700795 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
796 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
797 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
MÃ¥rten Kongstad60195a72022-09-20 14:14:20 +0200798 sdkversion = android::base::GetProperty("ro.build.version.sdk", "(unknown)");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700799 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
Colin Crossf45fa6b2012-03-26 12:38:26 -0700800
Felipe Lemed8b94e52016-12-08 10:21:44 -0800801 printf("========================================================\n");
802 printf("== dumpstate: %s\n", date);
803 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700804
Felipe Lemed8b94e52016-12-08 10:21:44 -0800805 printf("\n");
806 printf("Build: %s\n", build.c_str());
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700807 // NOTE: fingerprint entry format is important for other tools.
Felipe Lemed8b94e52016-12-08 10:21:44 -0800808 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
809 printf("Bootloader: %s\n", bootloader.c_str());
810 printf("Radio: %s\n", radio.c_str());
811 printf("Network: %s\n", network.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100812 int64_t module_metadata_version = android::os::GetModuleMetadataVersion();
813 if (module_metadata_version != 0) {
814 printf("Module Metadata version: %" PRId64 "\n", module_metadata_version);
815 }
MÃ¥rten Kongstad60195a72022-09-20 14:14:20 +0200816 printf("Android SDK version: %s\n", sdkversion.c_str());
817 printf("SDK extensions: ");
818 RunCommandToFd(STDOUT_FILENO, "", {SDK_EXT_INFO, "--header"},
819 CommandOptions::WithTimeout(1).Always().DropRoot().Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700820
Felipe Lemed8b94e52016-12-08 10:21:44 -0800821 printf("Kernel: ");
Felipe Lemef0292972016-11-22 13:57:05 -0800822 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
Felipe Lemed8b94e52016-12-08 10:21:44 -0800823 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
Devin Moore09fde8d2023-03-21 16:28:22 +0000824 printf("Bootconfig: ");
825 DumpFileToFd(STDOUT_FILENO, "", "/proc/bootconfig");
Felipe Leme7709f8a2017-12-05 09:30:09 -0800826 printf("Uptime: ");
827 RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"},
828 CommandOptions::WithTimeout(1).Always().Build());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800829 printf("Bugreport format version: %s\n", version_.c_str());
Kevin Jeonfa64e642023-07-27 11:36:41 -0400830 printf(
831 "Dumpstate info: id=%d pid=%d dry_run=%d parallel_run=%d strict_run=%d args=%s "
832 "bugreport_mode=%s\n",
833 id_, pid_, PropertiesHelper::IsDryRun(), PropertiesHelper::IsParallelRun(),
834 PropertiesHelper::IsStrictRun(), options_->args.c_str(),
835 options_->bugreport_mode_string.c_str());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800836 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800837}
838
Felipe Leme24b66ee2016-06-16 10:55:26 -0700839// List of file extensions that can cause a zip file attachment to be rejected by some email
840// service providers.
841static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
842 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
843 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
844 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
845};
846
Vishnu Naire97d6122018-01-18 13:58:56 -0800847status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd,
848 std::chrono::milliseconds timeout = 0ms) {
Felipe Leme24b66ee2016-06-16 10:55:26 -0700849 std::string valid_name = entry_name;
850
851 // Rename extension if necessary.
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -0700852 size_t idx = entry_name.rfind('.');
Felipe Leme24b66ee2016-06-16 10:55:26 -0700853 if (idx != std::string::npos) {
854 std::string extension = entry_name.substr(idx);
855 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
856 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
857 valid_name = entry_name + ".renamed";
858 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
859 }
860 }
861
Felipe Leme6fe9db62016-02-12 09:04:16 -0800862 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
863 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Kevin Jeon9bbe0ac2022-05-05 22:05:43 +0000864 size_t flags = ZipWriter::kCompress | ZipWriter::kDefaultCompression;
865 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), flags,
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700866 get_mtime(fd, ds.now_));
Felipe Leme1d486fe2016-10-14 18:06:47 -0700867 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700868 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700869 ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800870 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800871 }
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000872 bool finished_entry = false;
873 auto finish_entry = [this, &finished_entry] {
874 if (!finished_entry) {
875 // This should only be called when we're going to return an earlier error,
876 // which would've been logged. This may imply the file is already corrupt
877 // and any further logging from FinishEntry is more likely to mislead than
878 // not.
879 this->zip_writer_->FinishEntry();
880 }
881 };
882 auto scope_guard = android::base::make_scope_guard(finish_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -0800883 auto start = std::chrono::steady_clock::now();
884 auto end = start + timeout;
885 struct pollfd pfd = {fd, POLLIN};
Felipe Lemee82a27d2016-01-05 13:35:44 -0800886
Felipe Leme770410d2016-01-26 17:07:14 -0800887 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800888 while (1) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800889 if (timeout.count() > 0) {
890 // lambda to recalculate the timeout.
891 auto time_left_ms = [end]() {
892 auto now = std::chrono::steady_clock::now();
893 auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
894 return std::max(diff.count(), 0LL);
895 };
896
897 int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
898 if (rc < 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000899 MYLOGE("Error in poll while adding from fd to zip entry %s:%s\n",
900 entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800901 return -errno;
902 } else if (rc == 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000903 MYLOGE("Timed out adding from fd to zip entry %s:%s Timeout:%lldms\n",
Vishnu Naire97d6122018-01-18 13:58:56 -0800904 entry_name.c_str(), strerror(errno), timeout.count());
905 return TIMED_OUT;
906 }
907 }
908
Zach Riggle22200402016-08-18 01:01:24 -0400909 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800910 if (bytes_read == 0) {
911 break;
912 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800913 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800914 return -errno;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800915 }
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700916 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800917 if (err) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700918 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800919 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800920 }
921 }
922
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700923 err = zip_writer_->FinishEntry();
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000924 finished_entry = true;
Felipe Leme1d486fe2016-10-14 18:06:47 -0700925 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700926 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800927 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800928 }
929
Vishnu Naire97d6122018-01-18 13:58:56 -0800930 return OK;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800931}
932
Felipe Leme1d486fe2016-10-14 18:06:47 -0700933bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
934 android::base::unique_fd fd(
935 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700936 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800937 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800938 return false;
939 }
940
Vishnu Naire97d6122018-01-18 13:58:56 -0800941 return (AddZipEntryFromFd(entry_name, fd.get()) == OK);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800942}
943
944/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700945static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800946 return (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) == OK) ? 0 : 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800947}
948
Felipe Leme1d486fe2016-10-14 18:06:47 -0700949void Dumpstate::AddDir(const std::string& dir, bool recursive) {
Felipe Leme678727a2016-09-21 17:22:11 -0700950 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
Felipe Leme46b85da2016-11-21 17:40:45 -0800951 DurationReporter duration_reporter(dir, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700952 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800953}
954
Felipe Leme1d486fe2016-10-14 18:06:47 -0700955bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800956 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Kevin Jeon9bbe0ac2022-05-05 22:05:43 +0000957 size_t flags = ZipWriter::kCompress | ZipWriter::kDefaultCompression;
958 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), flags, ds.now_);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700959 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700960 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700961 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800962 return false;
963 }
964
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700965 err = zip_writer_->WriteBytes(content.c_str(), content.length());
Felipe Leme1d486fe2016-10-14 18:06:47 -0700966 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700967 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700968 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800969 return false;
970 }
971
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700972 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700973 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700974 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800975 return false;
976 }
977
978 return true;
979}
980
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800981static void DoKmsg() {
982 struct stat st;
983 if (!stat(PSTORE_LAST_KMSG, &st)) {
984 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
985 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
986 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
987 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
988 } else {
989 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
990 DumpFile("LAST KMSG", "/proc/last_kmsg");
991 }
992}
993
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800994static void DoKernelLogcat() {
Yao Chenbe3bbc12018-01-17 16:31:10 -0800995 unsigned long timeout_ms = logcat_timeout({"kernel"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800996 RunCommand(
997 "KERNEL LOG",
998 {"logcat", "-b", "kernel", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
999 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1000}
1001
Nandana Duttdb379fa2019-10-09 16:54:41 +01001002static void DoSystemLogcat(time_t since) {
1003 char since_str[80];
1004 strftime(since_str, sizeof(since_str), "%Y-%m-%d %H:%M:%S.000", localtime(&since));
1005
1006 unsigned long timeout_ms = logcat_timeout({"main", "system", "crash"});
1007 RunCommand("SYSTEM LOG",
1008 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v", "-T",
1009 since_str},
1010 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1011}
1012
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001013static void DoRadioLogcat() {
1014 unsigned long timeout_ms = logcat_timeout({"radio"});
1015 RunCommand(
1016 "RADIO LOG",
1017 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1018 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
1019}
1020
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001021static void DoLogcat() {
Vishnu Nair6921f802017-11-22 09:17:23 -08001022 unsigned long timeout_ms;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001023 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
1024 // calculate timeout
Yao Chenbe3bbc12018-01-17 16:31:10 -08001025 timeout_ms = logcat_timeout({"main", "system", "crash"});
Tony Makae737652017-03-30 17:47:09 +01001026 RunCommand("SYSTEM LOG",
Vishnu Nair6921f802017-11-22 09:17:23 -08001027 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1028 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -08001029 timeout_ms = logcat_timeout({"events"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001030 RunCommand(
1031 "EVENT LOG",
1032 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001033 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Yao Chenbe3bbc12018-01-17 16:31:10 -08001034 timeout_ms = logcat_timeout({"stats"});
1035 RunCommand(
1036 "STATS LOG",
1037 {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001038 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001039 DoRadioLogcat();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001040
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001041 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001042 RunCommand("LAST LOGCAT", {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable",
1043 "-v", "uid", "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001044}
1045
Mike Ma5c267872019-08-21 11:31:34 -07001046static void DumpIncidentReport() {
Mike Ma5c267872019-08-21 11:31:34 -07001047 const std::string path = ds.bugreport_internal_dir_ + "/tmp_incident_report";
1048 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1049 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1050 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1051 if (fd < 0) {
1052 MYLOGE("Could not open %s to dump incident report.\n", path.c_str());
1053 return;
1054 }
Kevin Jeonfa64e642023-07-27 11:36:41 -04001055 RunCommandToFd(fd, "", {"incident", "-u"},
1056 CommandOptions::WithTimeout(PropertiesHelper::IsStrictRun() ? 20 : 120).Build());
Mike Ma5c267872019-08-21 11:31:34 -07001057 bool empty = 0 == lseek(fd, 0, SEEK_END);
1058 if (!empty) {
1059 // Use a different name from "incident.proto"
1060 // /proto/incident.proto is reserved for incident service dump
1061 // i.e. metadata for debugging.
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001062 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "incident_report" + kProtoExt,
1063 path);
1064 } else {
1065 unlink(path.c_str());
Mike Ma5c267872019-08-21 11:31:34 -07001066 }
Mike Ma5c267872019-08-21 11:31:34 -07001067}
1068
Aaron Huang24d215d2022-04-27 18:51:16 +08001069static void DumpNetstatsProto() {
1070 const std::string path = ds.bugreport_internal_dir_ + "/tmp_netstats_proto";
1071 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1072 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1073 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1074 if (fd < 0) {
1075 MYLOGE("Could not open %s to dump netstats proto.\n", path.c_str());
1076 return;
1077 }
1078 RunCommandToFd(fd, "", {"dumpsys", "netstats", "--proto"},
Kevin Jeon2fb3dd62022-09-28 18:48:55 +00001079 CommandOptions::WithTimeout(5).Build());
Aaron Huang24d215d2022-04-27 18:51:16 +08001080 bool empty = 0 == lseek(fd, 0, SEEK_END);
1081 if (!empty) {
1082 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "netstats" + kProtoExt,
1083 path);
1084 } else {
1085 unlink(path.c_str());
1086 }
1087}
1088
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001089static void MaybeAddSystemTraceToZip() {
1090 // This function copies into the .zip the system trace that was snapshotted
Kean Mariottica20f2d2023-12-15 09:34:25 +00001091 // by the early call to MaybeSnapshotSystemTraceAsync(), if any background
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001092 // tracing was happening.
Kean Mariotti853b73a2023-07-27 12:40:30 +00001093 bool system_trace_exists = access(SYSTEM_TRACE_SNAPSHOT, F_OK) == 0;
1094 if (!system_trace_exists) {
Kean Mariottica20f2d2023-12-15 09:34:25 +00001095 // No background trace was happening at the time MaybeSnapshotSystemTraceAsync() was invoked
Kean Mariotti853b73a2023-07-27 12:40:30 +00001096 if (!PropertiesHelper::IsUserBuild()) {
1097 MYLOGI(
1098 "No system traces found. Check for previously uploaded traces by looking for "
1099 "go/trace-uuid in logcat")
1100 }
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001101 return;
1102 }
1103 ds.AddZipEntry(
1104 ZIP_ROOT_DIR + SYSTEM_TRACE_SNAPSHOT,
1105 SYSTEM_TRACE_SNAPSHOT);
1106 android::os::UnlinkAndLogOnError(SYSTEM_TRACE_SNAPSHOT);
1107}
1108
Sunny Goyal35949782019-11-19 15:54:36 -08001109static void DumpVisibleWindowViews() {
Sunny Goyal35949782019-11-19 15:54:36 -08001110 DurationReporter duration_reporter("VISIBLE WINDOW VIEWS");
1111 const std::string path = ds.bugreport_internal_dir_ + "/tmp_visible_window_views";
1112 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1113 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1114 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1115 if (fd < 0) {
1116 MYLOGE("Could not open %s to dump visible views.\n", path.c_str());
1117 return;
1118 }
1119 RunCommandToFd(fd, "", {"cmd", "window", "dump-visible-window-views"},
Kevin Jeon774abde2022-09-28 18:20:43 +00001120 CommandOptions::WithTimeout(10).Build());
Sunny Goyal35949782019-11-19 15:54:36 -08001121 bool empty = 0 == lseek(fd, 0, SEEK_END);
1122 if (!empty) {
1123 ds.AddZipEntry("visible_windows.zip", path);
1124 } else {
1125 MYLOGW("Failed to dump visible windows\n");
1126 }
1127 unlink(path.c_str());
1128}
1129
Jayachandran Ca94c7172017-06-10 15:08:12 -07001130static void DumpIpTablesAsRoot() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001131 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
1132 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +09001133 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001134 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +09001135 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
1136 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
1137 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
1138 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001139}
1140
Woody Lin20767a92022-11-29 15:50:24 +08001141static void DumpShutdownCheckpoints() {
1142 const bool shutdown_checkpoints_dumped = AddDumps(
1143 ds.shutdown_checkpoints_.begin(), ds.shutdown_checkpoints_.end(),
1144 "SHUTDOWN CHECKPOINTS", false /* add_to_zip */);
1145 if (!shutdown_checkpoints_dumped) {
1146 printf("*** NO SHUTDOWN CHECKPOINTS to dump in %s\n\n",
1147 SHUTDOWN_CHECKPOINTS_DIR.c_str());
1148 }
1149}
1150
David Andersond9ba4752018-12-11 18:26:59 -08001151static void DumpDynamicPartitionInfo() {
1152 if (!::android::base::GetBoolProperty("ro.boot.dynamic_partitions", false)) {
1153 return;
1154 }
1155
1156 RunCommand("LPDUMP", {"lpdump", "--all"});
David Anderson6650ade2019-10-02 15:18:59 -07001157 RunCommand("DEVICE-MAPPER", {"gsid", "dump-device-mapper"});
David Andersond9ba4752018-12-11 18:26:59 -08001158}
1159
Chris Morin5a50d482022-02-01 17:41:18 -08001160static void AddAnrTraceDir(const std::string& anr_traces_dir) {
Narayan Kamath8f788292017-05-25 13:20:39 +01001161 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
1162 anr_traces_dir.c_str());
1163
1164 // If we're here, dump_traces_path will always be a temporary file
1165 // (created with mkostemp or similar) that contains dumps taken earlier
1166 // on in the process.
1167 if (dump_traces_path != nullptr) {
Chris Morin5a50d482022-02-01 17:41:18 -08001168 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
1169 dump_traces_path);
1170 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
Narayan Kamath8f788292017-05-25 13:20:39 +01001171
1172 const int ret = unlink(dump_traces_path);
1173 if (ret == -1) {
1174 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
1175 strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -07001176 }
1177 }
1178
Narayan Kamathbd863722017-06-01 18:50:12 +01001179 // Add a specific message for the first ANR Dump.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001180 if (ds.anr_data_.size() > 0) {
Chris Morin5a50d482022-02-01 17:41:18 -08001181 // The "last" ANR will always be present in the body of the main entry.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001182 AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1,
Chris Morin5a50d482022-02-01 17:41:18 -08001183 "VM TRACES AT LAST ANR", false /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001184
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001185 // Historical ANRs are always included as separate entries in the bugreport zip file.
Chris Morin5a50d482022-02-01 17:41:18 -08001186 AddDumps(ds.anr_data_.begin(), ds.anr_data_.end(),
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001187 "HISTORICAL ANR", true /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001188 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +01001189 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
1190 }
Andy Hungd62f7e62024-01-11 15:47:52 -08001191
1192 // Add Java anr traces (such as generated by the Finalizer Watchdog).
1193 AddDumps(ds.anr_trace_data_.begin(), ds.anr_trace_data_.end(), "JAVA ANR TRACES",
1194 true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001195}
1196
1197static void AddAnrTraceFiles() {
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001198 std::string anr_traces_dir = "/data/anr";
Narayan Kamath8f788292017-05-25 13:20:39 +01001199
Chris Morin5a50d482022-02-01 17:41:18 -08001200 AddAnrTraceDir(anr_traces_dir);
Narayan Kamath8f788292017-05-25 13:20:39 +01001201
Makoto Onuki83ec63f2019-01-31 17:08:59 -08001202 RunCommand("ANR FILES", {"ls", "-lt", ANR_DIR});
1203
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001204 // Slow traces for slow operations.
Felipe Lemee184f662016-10-27 10:04:47 -07001205 struct stat st;
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001206 int i = 0;
1207 while (true) {
1208 const std::string slow_trace_path =
1209 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
1210 if (stat(slow_trace_path.c_str(), &st)) {
1211 // No traces file at this index, done with the files.
1212 break;
Felipe Lemee184f662016-10-27 10:04:47 -07001213 }
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001214 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
1215 i++;
Felipe Lemee184f662016-10-27 10:04:47 -07001216 }
1217}
1218
Wei Wang509bb5d2017-06-09 14:42:12 -07001219static void DumpBlockStatFiles() {
1220 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -07001221
Wei Wang1dc1ef52017-06-12 11:28:37 -07001222 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
1223
1224 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001225 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1226 return;
1227 }
1228
1229 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -07001230 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001231 if ((d->d_name[0] == '.')
1232 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1233 || (d->d_name[1] == '\0'))) {
1234 continue;
1235 }
1236 const std::string new_path =
1237 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1238 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1239 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1240 printf("\n");
1241 }
Wei Wang1dc1ef52017-06-12 11:28:37 -07001242 return;
Wei Wang509bb5d2017-06-09 14:42:12 -07001243}
Jayachandran Ca94c7172017-06-10 15:08:12 -07001244
1245static void DumpPacketStats() {
1246 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
Jayachandran Ca94c7172017-06-10 15:08:12 -07001247}
1248
1249static void DumpIpAddrAndRules() {
1250 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
Ray Chencbf278a2023-11-20 07:49:45 +00001251 RunCommand("NETWORK INTERFACES", {"ip", "-s", "link"});
Jayachandran Ca94c7172017-06-10 15:08:12 -07001252 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1253 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1254 RunCommand("IP RULES", {"ip", "rule", "show"});
1255 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1256}
1257
Nandana Dutt5c390032019-03-12 10:52:56 +00001258static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, int priority,
1259 std::chrono::milliseconds timeout,
1260 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001261 auto start = std::chrono::steady_clock::now();
Vishnu Naire97d6122018-01-18 13:58:56 -08001262 sp<android::IServiceManager> sm = defaultServiceManager();
1263 Dumpsys dumpsys(sm.get());
Vishnu Naire97d6122018-01-18 13:58:56 -08001264 Vector<String16> args;
1265 Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
Vishnu Naire97d6122018-01-18 13:58:56 -08001266 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1267 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001268 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001269 std::string path(title);
1270 path.append(" - ").append(String8(service).c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -08001271 size_t bytes_written = 0;
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001272 if (PropertiesHelper::IsDryRun()) {
1273 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1274 dumpsys.writeDumpFooter(STDOUT_FILENO, service, std::chrono::milliseconds(1));
1275 } else {
Devin Mooref492c1a2023-03-15 19:19:03 +00001276 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP | Dumpsys::TYPE_PID |
1277 Dumpsys::TYPE_CLIENTS | Dumpsys::TYPE_THREAD,
Devin Mooreae68df22023-02-24 20:59:51 +00001278 service, args);
1279 if (status == OK) {
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001280 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1281 std::chrono::duration<double> elapsed_seconds;
1282 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH &&
1283 service == String16("meminfo")) {
1284 // Use a longer timeout for meminfo, since 30s is not always enough.
1285 status = dumpsys.writeDump(STDOUT_FILENO, service, 60s,
1286 /* as_proto = */ false, elapsed_seconds,
1287 bytes_written);
1288 } else {
1289 status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
1290 /* as_proto = */ false, elapsed_seconds,
1291 bytes_written);
1292 }
1293 dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
1294 bool dump_complete = (status == OK);
1295 dumpsys.stopDumpThread(dump_complete);
Devin Moorecdfa4602023-03-16 20:49:39 +00001296 } else {
1297 MYLOGE("Failed to start dump thread for service: %s, status: %d",
1298 String8(service).c_str(), status);
Gavin Corkeryfac7e2b2021-07-08 22:39:02 +01001299 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001300 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001301
1302 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1303 std::chrono::steady_clock::now() - start);
1304 if (elapsed_duration > timeout) {
1305 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1306 elapsed_duration.count());
1307 break;
1308 }
1309 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001310 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001311}
1312
Vishnu Nair64afc022018-02-01 15:29:34 -08001313static void RunDumpsysText(const std::string& title, int priority,
1314 std::chrono::milliseconds timeout,
1315 std::chrono::milliseconds service_timeout) {
1316 DurationReporter duration_reporter(title);
1317 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1318 fsync(STDOUT_FILENO);
1319 RunDumpsysTextByPriority(title, priority, timeout, service_timeout);
1320}
1321
1322/* Dump all services registered with Normal or Default priority. */
Nandana Dutt5c390032019-03-12 10:52:56 +00001323static Dumpstate::RunStatus RunDumpsysTextNormalPriority(const std::string& title,
1324 std::chrono::milliseconds timeout,
1325 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001326 DurationReporter duration_reporter(title);
1327 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1328 fsync(STDOUT_FILENO);
1329 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout,
1330 service_timeout);
Nandana Dutt5c390032019-03-12 10:52:56 +00001331
1332 RETURN_IF_USER_DENIED_CONSENT();
1333
1334 return RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1335 service_timeout);
Vishnu Nair64afc022018-02-01 15:29:34 -08001336}
1337
Nandana Dutt5c390032019-03-12 10:52:56 +00001338static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priority,
1339 std::chrono::milliseconds timeout,
1340 std::chrono::milliseconds service_timeout) {
Vishnu Naire97d6122018-01-18 13:58:56 -08001341 sp<android::IServiceManager> sm = defaultServiceManager();
1342 Dumpsys dumpsys(sm.get());
1343 Vector<String16> args;
1344 Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
1345 DurationReporter duration_reporter(title);
1346
1347 auto start = std::chrono::steady_clock::now();
1348 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
1349 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001350 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001351 std::string path(kProtoPath);
1352 path.append(String8(service).c_str());
1353 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
1354 path.append("_CRITICAL");
1355 } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
1356 path.append("_HIGH");
1357 }
1358 path.append(kProtoExt);
Steven Morelandcbd69fc2021-07-20 20:45:43 +00001359 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP, service, args);
Vishnu Naire97d6122018-01-18 13:58:56 -08001360 if (status == OK) {
1361 status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
1362 bool dumpTerminated = (status == OK);
1363 dumpsys.stopDumpThread(dumpTerminated);
1364 }
1365 ZipWriter::FileEntry file_entry;
1366 ds.zip_writer_->GetLastEntry(&file_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -08001367
1368 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1369 std::chrono::steady_clock::now() - start);
1370 if (elapsed_duration > timeout) {
1371 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1372 elapsed_duration.count());
1373 break;
1374 }
1375 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001376 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001377}
1378
Nandana Dutta7db6342018-11-21 14:53:34 +00001379// Runs dumpsys on services that must dump first and will take less than 100ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001380static Dumpstate::RunStatus RunDumpsysCritical() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001381 RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1382 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Nandana Dutt5c390032019-03-12 10:52:56 +00001383
1384 RETURN_IF_USER_DENIED_CONSENT();
1385
1386 return RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1387 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Vishnu Nair780b1282017-10-10 13:57:24 -07001388}
1389
1390// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001391static Dumpstate::RunStatus RunDumpsysHigh() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001392 // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
1393 // high priority. Reduce timeout once they are able to dump in a shorter time or
1394 // moved to a parallel task.
1395 RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1396 /* timeout= */ 90s, /* service_timeout= */ 30s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001397
1398 RETURN_IF_USER_DENIED_CONSENT();
1399
1400 return RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1401 /* timeout= */ 5s, /* service_timeout= */ 1s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001402}
1403
1404// Runs dumpsys on services that must dump but can take up to 10s to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001405static Dumpstate::RunStatus RunDumpsysNormal() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001406 RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001407
1408 RETURN_IF_USER_DENIED_CONSENT();
1409
1410 return RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1411 /* timeout= */ 90s, /* service_timeout= */ 10s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001412}
1413
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001414/*
1415 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1416 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1417 * if it's not running in the parallel task.
1418 */
1419static void DumpHals(int out_fd = STDOUT_FILENO) {
Yifan Hong30528a22020-08-07 18:24:06 -07001420 RunCommand("HARDWARE HALS", {"lshal", "--all", "--types=all"},
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001421 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build(),
1422 false, out_fd);
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001423
Steven Moreland44cd9482018-01-04 16:24:13 -08001424 using android::hidl::manager::V1_0::IServiceManager;
1425 using android::hardware::defaultServiceManager;
1426
1427 sp<IServiceManager> sm = defaultServiceManager();
1428 if (sm == nullptr) {
1429 MYLOGE("Could not retrieve hwservicemanager to dump hals.\n");
1430 return;
1431 }
1432
1433 auto ret = sm->list([&](const auto& interfaces) {
1434 for (const std::string& interface : interfaces) {
1435 std::string cleanName = interface;
Steven Morelandc6b1fc22023-07-26 23:53:58 +00001436 std::replace_if(
1437 cleanName.begin(), cleanName.end(),
1438 [](char c) {
1439 return !isalnum(c) && std::string("@-_.").find(c) == std::string::npos;
1440 },
1441 '_');
Nandana Dutt979388e2018-11-30 16:48:55 +00001442 const std::string path = ds.bugreport_internal_dir_ + "/lshal_debug_" + cleanName;
Steven Moreland44cd9482018-01-04 16:24:13 -08001443
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001444 bool empty = false;
Steven Moreland44cd9482018-01-04 16:24:13 -08001445 {
1446 auto fd = android::base::unique_fd(
1447 TEMP_FAILURE_RETRY(open(path.c_str(),
1448 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1449 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1450 if (fd < 0) {
1451 MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str());
1452 continue;
1453 }
1454 RunCommandToFd(fd,
1455 "",
Steven Morelandc81cd3c2018-01-18 14:36:26 -08001456 {"lshal", "debug", "-E", interface},
Steven Moreland44cd9482018-01-04 16:24:13 -08001457 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1458
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001459 empty = 0 == lseek(fd, 0, SEEK_END);
Steven Moreland44cd9482018-01-04 16:24:13 -08001460 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001461 if (!empty) {
1462 ds.EnqueueAddZipEntryAndCleanupIfNeeded("lshal-debug/" + cleanName + ".txt",
1463 path);
1464 } else {
1465 unlink(path.c_str());
1466 }
Steven Moreland44cd9482018-01-04 16:24:13 -08001467 }
1468 });
1469
1470 if (!ret.isOk()) {
1471 MYLOGE("Could not list hals from hwservicemanager.\n");
1472 }
1473}
1474
Devin Moore8df81bb2022-06-08 22:47:02 +00001475// Dump all of the files that make up the vendor interface.
1476// See the files listed in dumpFileList() for the latest list of files.
1477static void DumpVintf() {
Devin Moore16271d92022-09-22 18:28:48 +00001478
1479 const std::string sku = android::base::GetProperty("ro.boot.product.hardware.sku", "");
1480 const auto vintfFiles = android::vintf::details::dumpFileList(sku);
Devin Moore8df81bb2022-06-08 22:47:02 +00001481 for (const auto vintfFile : vintfFiles) {
1482 struct stat st;
1483 if (stat(vintfFile.c_str(), &st) == 0) {
1484 if (S_ISDIR(st.st_mode)) {
1485 ds.AddDir(vintfFile, true /* recursive */);
1486 } else {
1487 ds.EnqueueAddZipEntryAndCleanupIfNeeded(ZIP_ROOT_DIR + vintfFile,
1488 vintfFile);
1489 }
1490 }
1491 }
1492}
1493
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001494static void DumpExternalFragmentationInfo() {
1495 struct stat st;
1496 if (stat("/proc/buddyinfo", &st) != 0) {
1497 MYLOGE("Unable to dump external fragmentation info\n");
1498 return;
1499 }
1500
1501 printf("------ EXTERNAL FRAGMENTATION INFO ------\n");
1502 std::ifstream ifs("/proc/buddyinfo");
1503 auto unusable_index_regex = std::regex{"Node\\s+([0-9]+),\\s+zone\\s+(\\S+)\\s+(.*)"};
1504 for (std::string line; std::getline(ifs, line);) {
1505 std::smatch match_results;
1506 if (std::regex_match(line, match_results, unusable_index_regex)) {
1507 std::stringstream free_pages(std::string{match_results[3]});
1508 std::vector<int> free_pages_per_order(std::istream_iterator<int>{free_pages},
1509 std::istream_iterator<int>());
1510
1511 int total_free_pages = 0;
1512 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1513 total_free_pages += (free_pages_per_order[i] * std::pow(2, i));
1514 }
1515
1516 printf("Node %s, zone %8s", match_results[1].str().c_str(),
1517 match_results[2].str().c_str());
1518
1519 int usable_free_pages = total_free_pages;
1520 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1521 auto unusable_index = (total_free_pages - usable_free_pages) /
1522 static_cast<double>(total_free_pages);
1523 printf(" %5.3f", unusable_index);
1524 usable_free_pages -= (free_pages_per_order[i] * std::pow(2, i));
1525 }
1526
1527 printf("\n");
1528 }
1529 }
1530 printf("\n");
1531}
1532
mhasankd451a472020-05-26 18:02:39 -07001533static void DumpstateLimitedOnly() {
EdenSue8fe4522023-11-20 15:37:23 +08001534 // Trimmed-down version of dumpstate to only include a allowlisted
mhasankd451a472020-05-26 18:02:39 -07001535 // set of logs (system log, event log, and system server / system app
1536 // crashes, and networking logs). See b/136273873 and b/138459828
1537 // for context.
1538 DurationReporter duration_reporter("DUMPSTATE");
1539 unsigned long timeout_ms;
1540 // calculate timeout
1541 timeout_ms = logcat_timeout({"main", "system", "crash"});
1542 RunCommand("SYSTEM LOG",
1543 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1544 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1545 timeout_ms = logcat_timeout({"events"});
1546 RunCommand(
1547 "EVENT LOG",
1548 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1549 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1550
1551 printf("========================================================\n");
1552 printf("== Networking Service\n");
1553 printf("========================================================\n");
1554
1555 RunDumpsys("DUMPSYS NETWORK_SERVICE_LIMITED", {"wifi", "-a"},
1556 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hugo Benichiaa162682020-10-30 23:28:56 +09001557 RunDumpsys("DUMPSYS CONNECTIVITY REQUESTS", {"connectivity", "requests"},
1558 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
mhasankd451a472020-05-26 18:02:39 -07001559
1560 printf("========================================================\n");
1561 printf("== Dropbox crashes\n");
1562 printf("========================================================\n");
1563
1564 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1565 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1566
Bryan Yuefb85d92024-02-02 13:37:06 +00001567
1568 printf("========================================================\n");
1569 printf("== ANR Traces\n");
1570 printf("========================================================\n");
1571
1572 AddAnrTraceFiles();
1573
mhasankd451a472020-05-26 18:02:39 -07001574 printf("========================================================\n");
1575 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1576 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1577 printf("========================================================\n");
1578 printf("== dumpstate: done (id %d)\n", ds.id_);
1579 printf("========================================================\n");
1580}
1581
Rhed Jaoe017f982020-07-21 17:58:41 +08001582/*
1583 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1584 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1585 * if it's not running in the parallel task.
1586 */
1587static void DumpCheckins(int out_fd = STDOUT_FILENO) {
1588 dprintf(out_fd, "========================================================\n");
1589 dprintf(out_fd, "== Checkins\n");
1590 dprintf(out_fd, "========================================================\n");
1591
1592 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"}, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001593 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"}, out_fd);
1594 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"}, out_fd);
1595 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"}, out_fd);
1596 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"}, out_fd);
1597}
1598
1599/*
1600 * Runs dumpsys on activity service to dump all application activities, services
1601 * and providers in the device.
1602 *
1603 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1604 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1605 * if it's not running in the parallel task.
1606 */
1607static void DumpAppInfos(int out_fd = STDOUT_FILENO) {
1608 dprintf(out_fd, "========================================================\n");
1609 dprintf(out_fd, "== Running Application Activities\n");
1610 dprintf(out_fd, "========================================================\n");
1611
1612 // The following dumpsys internally collects output from running apps, so it can take a long
1613 // time. So let's extend the timeout.
1614
1615 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1616
1617 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1618
1619 dprintf(out_fd, "========================================================\n");
1620 dprintf(out_fd, "== Running Application Services (platform)\n");
1621 dprintf(out_fd, "========================================================\n");
1622
1623 RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
1624 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1625
1626 dprintf(out_fd, "========================================================\n");
1627 dprintf(out_fd, "== Running Application Services (non-platform)\n");
1628 dprintf(out_fd, "========================================================\n");
1629
1630 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1631 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1632
1633 dprintf(out_fd, "========================================================\n");
1634 dprintf(out_fd, "== Running Application Providers (platform)\n");
1635 dprintf(out_fd, "========================================================\n");
1636
1637 RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
Rhed Jaob049f182021-01-11 21:08:43 +08001638 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001639
1640 dprintf(out_fd, "========================================================\n");
1641 dprintf(out_fd, "== Running Application Providers (non-platform)\n");
1642 dprintf(out_fd, "========================================================\n");
1643
1644 RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1645 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1646}
1647
Nandana Dutt5c390032019-03-12 10:52:56 +00001648// Dumps various things. Returns early with status USER_CONSENT_DENIED if user denies consent
1649// via the consent they are shown. Ignores other errors that occur while running various
1650// commands. The consent checking is currently done around long running tasks, which happen to
1651// be distributed fairly evenly throughout the function.
Kean Mariotti306633e2022-09-05 16:30:47 +00001652Dumpstate::RunStatus Dumpstate::dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001653 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001654
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001655 // Enqueue slow functions into the thread pool, if the parallel run is enabled.
Aaron Huang24d215d2022-04-27 18:51:16 +08001656 std::future<std::string> dump_hals, dump_incident_report, dump_board, dump_checkins,
Kean Mariottica20f2d2023-12-15 09:34:25 +00001657 dump_netstats_report;
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001658 if (ds.dump_pool_) {
1659 // Pool was shutdown in DumpstateDefaultAfterCritical method in order to
Kean Mariotti306633e2022-09-05 16:30:47 +00001660 // drop root user. Restarts it.
1661 ds.dump_pool_->start(/* thread_counts = */3);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001662
Chris Morinbc223142022-02-04 14:17:11 -08001663 dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
1664 dump_incident_report = ds.dump_pool_->enqueueTask(
1665 DUMP_INCIDENT_REPORT_TASK, &DumpIncidentReport);
Aaron Huang24d215d2022-04-27 18:51:16 +08001666 dump_netstats_report = ds.dump_pool_->enqueueTask(
1667 DUMP_NETSTATS_PROTO_TASK, &DumpNetstatsProto);
Chris Morinbc223142022-02-04 14:17:11 -08001668 dump_board = ds.dump_pool_->enqueueTaskWithFd(
1669 DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
1670 dump_checkins = ds.dump_pool_->enqueueTaskWithFd(DUMP_CHECKINS_TASK, &DumpCheckins, _1);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001671 }
1672
Nandana Dutt5c390032019-03-12 10:52:56 +00001673 // Dump various things. Note that anything that takes "long" (i.e. several seconds) should
1674 // check intermittently (if it's intrerruptable like a foreach on pids) and/or should be wrapped
1675 // in a consent check (via RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK).
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001676 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001677 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001678 DumpBlockStatFiles();
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001679 DumpFile("MEMORY INFO", "/proc/meminfo");
1680 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001681 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001682
Kevin Jeon947922b2022-09-21 00:29:18 +00001683 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "BUGREPORT_PROCDUMP", {"bugreport_procdump"},
1684 CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001685
Sunny Goyal35949782019-11-19 15:54:36 -08001686 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpVisibleWindowViews);
1687
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001688 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1689 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1690 DumpFile("SLAB INFO", "/proc/slabinfo");
1691 DumpFile("ZONEINFO", "/proc/zoneinfo");
1692 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1693 DumpFile("BUDDYINFO", "/proc/buddyinfo");
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001694 DumpExternalFragmentationInfo();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001695
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001696 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001697
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001698 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001699 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001700
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001701 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001702 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_hals));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001703 } else {
1704 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_HALS_TASK, DumpHals);
1705 }
Steven Moreland81b429e2017-01-31 19:50:46 -08001706
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001707 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001708 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001709 struct stat s;
1710 if (stat("/proc/modules", &s) != 0) {
1711 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1712 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001713 RunCommand("LSMOD", {"lsmod"});
Woody Linc198f252021-05-04 16:37:11 +08001714 RunCommand("MODULES INFO",
1715 {"sh", "-c", "cat /proc/modules | cut -d' ' -f1 | "
1716 " while read MOD ; do echo modinfo:$MOD ; modinfo $MOD ; "
1717 "done"}, CommandOptions::AS_ROOT);
Felipe Lemee4eca582016-06-10 17:48:08 -07001718 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001719
Tom Cherryb87dbfa2020-07-28 11:28:53 -07001720 if (android::base::GetBoolProperty("ro.logd.kernel", false)) {
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001721 DoKernelLogcat();
1722 } else {
1723 do_dmesg();
1724 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001725
Devin Moore8df81bb2022-06-08 22:47:02 +00001726 DumpVintf();
1727
Felipe Lemef0292972016-11-22 13:57:05 -08001728 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001729
Jeff Brown1dc94e32014-09-11 14:15:27 -07001730 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001731 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001732
Jack Yu5a6b2e22020-08-14 18:13:35 +08001733 /* Dump Nfc NCI logs */
1734 ds.AddDir("/data/misc/nfc/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001735
Paul Chang0d2aad72020-02-13 20:04:03 +08001736 if (ds.options_->do_screenshot && !ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001737 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001738 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001739 }
1740
Felipe Lemee184f662016-10-27 10:04:47 -07001741 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001742
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001743 MaybeAddSystemTraceToZip();
1744
Narayan Kamath8f788292017-05-25 13:20:39 +01001745 // NOTE: tombstones are always added as separate entries in the zip archive
1746 // and are not interspersed with the main report.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001747 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
Narayan Kamathbd863722017-06-01 18:50:12 +01001748 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001749 if (!tombstones_dumped) {
1750 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001751 }
1752
Jayachandran Ca94c7172017-06-10 15:08:12 -07001753 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001754
Lorenzo Colitti807f2dd2022-05-27 12:48:37 +09001755 RunDumpsys("EBPF MAP STATS", {"connectivity", "trafficcontroller"});
Chenbo Feng276a3b62018-08-07 11:44:49 -07001756
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001757 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001758
Woody Lin20767a92022-11-29 15:50:24 +08001759 DumpShutdownCheckpoints();
1760
Jayachandran Ca94c7172017-06-10 15:08:12 -07001761 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001762
1763 dump_route_tables();
1764
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001765 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1766 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1767 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001768
Nandana Dutt5c390032019-03-12 10:52:56 +00001769 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysHigh);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001770
Chiachang Wang668ede42021-05-17 17:14:20 +08001771 // The dump mechanism in connectivity is refactored due to modularization work. Connectivity can
1772 // only register with a default priority(NORMAL priority). Dumpstate has to call connectivity
1773 // dump with priority parameters to dump high priority information.
1774 RunDumpsys("SERVICE HIGH connectivity", {"connectivity", "--dump-priority", "HIGH"},
1775 CommandOptions::WithTimeout(10).Build());
1776
Elliott Hughes23ccc622017-02-28 10:14:22 -08001777 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001778
Joe Onoratod38bc3a2023-06-29 15:48:28 -07001779 DumpFile("SYSTEM BUILD-TIME RELEASE FLAGS", "/system/etc/build_flags.json");
1780 DumpFile("SYSTEM_EXT BUILD-TIME RELEASE FLAGS", "/system_ext/etc/build_flags.json");
1781 DumpFile("PRODUCT BUILD-TIME RELEASE FLAGS", "/product/etc/build_flags.json");
1782 DumpFile("VENDOR BUILD-TIME RELEASE FLAGS", "/vendor/etc/build_flags.json");
1783
MÃ¥rten Kongstad5ad813f2023-09-28 10:09:18 +02001784 RunCommand("ACONFIG FLAGS", {PRINT_FLAGS},
1785 CommandOptions::WithTimeout(10).Always().DropRoot().Build());
Joe Onoratod38bc3a2023-06-29 15:48:28 -07001786
Jin Qianf334d662017-10-10 14:41:37 -07001787 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001788
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001789 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001790
Colin Crossf45fa6b2012-03-26 12:38:26 -07001791 /* Binder state is expensive to look at as it uses a lot of memory. */
Hridya Valsaraju920ba712020-02-09 16:27:01 -08001792 std::string binder_logs_dir = access("/dev/binderfs/binder_logs", R_OK) ?
1793 "/sys/kernel/debug/binder" : "/dev/binderfs/binder_logs";
1794
1795 DumpFile("BINDER FAILED TRANSACTION LOG", binder_logs_dir + "/failed_transaction_log");
1796 DumpFile("BINDER TRANSACTION LOG", binder_logs_dir + "/transaction_log");
1797 DumpFile("BINDER TRANSACTIONS", binder_logs_dir + "/transactions");
1798 DumpFile("BINDER STATS", binder_logs_dir + "/stats");
1799 DumpFile("BINDER STATE", binder_logs_dir + "/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001800
Yifan Hongd90cc652020-02-08 16:52:02 -08001801 ds.AddDir(SNAPSHOTCTL_LOG_DIR, false);
1802
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001803 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001804 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_board));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001805 } else {
1806 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
1807 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001808
Steven Moreland7440ddb2016-12-15 16:13:39 -08001809 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001810 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1811 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001812 // su does not exist on user builds, so try running without it.
1813 // This way any implementations of vril-dump that do not require
1814 // root can run on user builds.
1815 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001816 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001817 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001818 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001819 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001820 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001821 }
1822
Felipe Lemed8b94e52016-12-08 10:21:44 -08001823 printf("========================================================\n");
1824 printf("== Android Framework Services\n");
1825 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001826
Nandana Dutt5c390032019-03-12 10:52:56 +00001827 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001828
Jack He91ff2fe2021-02-18 18:23:43 -08001829 /* Dump Bluetooth HCI logs after getting bluetooth_manager dumpsys */
1830 ds.AddDir("/data/misc/bluetooth/logs", true);
1831
Rhed Jaoe017f982020-07-21 17:58:41 +08001832 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001833 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_checkins));
Rhed Jaoe017f982020-07-21 17:58:41 +08001834 } else {
1835 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_CHECKINS_TASK, DumpCheckins);
1836 }
Dianne Hackborn02bea972013-06-26 18:59:09 -07001837
Rhed Jaoc5f7ec32020-12-22 22:11:08 +08001838 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpAppInfos);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001839
Adrian Roos8b397ab2017-04-04 16:35:44 -07001840 printf("========================================================\n");
1841 printf("== Dropbox crashes\n");
1842 printf("========================================================\n");
1843
1844 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1845 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1846
Felipe Lemed8b94e52016-12-08 10:21:44 -08001847 printf("========================================================\n");
1848 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1849 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1850 printf("========================================================\n");
1851 printf("== dumpstate: done (id %d)\n", ds.id_);
1852 printf("========================================================\n");
Bookatz38472142018-09-28 10:20:24 -07001853
1854 printf("========================================================\n");
1855 printf("== Obtaining statsd metadata\n");
1856 printf("========================================================\n");
1857 // This differs from the usual dumpsys stats, which is the stats report data.
1858 RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
Mike Ma5c267872019-08-21 11:31:34 -07001859
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +09001860 // Add linker configuration directory
1861 ds.AddDir(LINKERCONFIG_DIR, true);
1862
Li Li830179f2022-01-04 12:53:29 -08001863 /* Dump frozen cgroupfs */
1864 dump_frozen_cgroupfs();
Li Li2eedd412021-06-30 15:11:53 -07001865
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001866 if (ds.dump_pool_) {
Aaron Huang24d215d2022-04-27 18:51:16 +08001867 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_netstats_report));
1868 } else {
1869 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_NETSTATS_PROTO_TASK,
1870 DumpNetstatsProto);
1871 }
1872
1873 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001874 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_incident_report));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001875 } else {
1876 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_INCIDENT_REPORT_TASK,
1877 DumpIncidentReport);
1878 }
Mike Ma5c267872019-08-21 11:31:34 -07001879
Kean Mariotti306633e2022-09-05 16:30:47 +00001880 MaybeAddUiTracesToZip();
1881
Nandana Dutt5c390032019-03-12 10:52:56 +00001882 return Dumpstate::RunStatus::OK;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001883}
1884
Nandana Dutt5c390032019-03-12 10:52:56 +00001885/*
1886 * Dumps state for the default case; drops root after it's no longer necessary.
1887 *
1888 * Returns RunStatus::OK if everything went fine.
1889 * Returns RunStatus::ERROR if there was an error.
1890 * Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport
1891 * with the caller.
1892 */
Jichao Lie89d9c12019-11-21 19:02:51 -08001893Dumpstate::RunStatus Dumpstate::DumpstateDefaultAfterCritical() {
Nandana Duttdb379fa2019-10-09 16:54:41 +01001894 // Capture first logcat early on; useful to take a snapshot before dumpstate logs take over the
1895 // buffer.
1896 DoLogcat();
1897 // Capture timestamp after first logcat to use in next logcat
1898 time_t logcat_ts = time(nullptr);
1899
Nandana Dutt4be45d12018-09-26 15:04:23 +01001900 /* collect stack traces from Dalvik and native processes (needs root) */
Chris Morinbc223142022-02-04 14:17:11 -08001901 std::future<std::string> dump_traces;
Rhed Jao5377d792020-07-16 17:37:39 +08001902 if (dump_pool_) {
1903 RETURN_IF_USER_DENIED_CONSENT();
1904 // One thread is enough since we only need to enqueue DumpTraces here.
1905 dump_pool_->start(/* thread_counts = */1);
1906
1907 // DumpTraces takes long time, post it to the another thread in the
1908 // pool, if pool is available
Chris Morinbc223142022-02-04 14:17:11 -08001909 dump_traces = dump_pool_->enqueueTask(
1910 DUMP_TRACES_TASK, &Dumpstate::DumpTraces, &ds, &dump_traces_path);
Rhed Jao5377d792020-07-16 17:37:39 +08001911 } else {
1912 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_TRACES_TASK, ds.DumpTraces,
1913 &dump_traces_path);
1914 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001915
1916 /* Run some operations that require root. */
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001917 if (!PropertiesHelper::IsDryRun()) {
Chris Morinc2cba7a2022-02-01 17:06:50 -08001918 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX);
1919 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX);
Andy Hungd62f7e62024-01-11 15:47:52 -08001920 ds.anr_trace_data_ = GetDumpFds(ANR_DIR, ANR_TRACE_FILE_PREFIX);
Woody Lin20767a92022-11-29 15:50:24 +08001921 ds.shutdown_checkpoints_ = GetDumpFds(
1922 SHUTDOWN_CHECKPOINTS_DIR, SHUTDOWN_CHECKPOINTS_FILE_PREFIX);
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001923 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001924
1925 ds.AddDir(RECOVERY_DIR, true);
1926 ds.AddDir(RECOVERY_DATA_DIR, true);
1927 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
Kelvin Zhang6eaa0f92022-09-12 09:29:19 -07001928 ds.AddDir(UPDATE_ENGINE_PREF_DIR, true);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001929 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1930 if (!PropertiesHelper::IsUserBuild()) {
1931 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1932 ds.AddDir(PROFILE_DATA_DIR_REF, true);
Calin Juravlef84d3692020-04-28 15:31:12 -07001933 ds.AddZipEntry(ZIP_ROOT_DIR + PACKAGE_DEX_USE_LIST, PACKAGE_DEX_USE_LIST);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001934 }
Jerry Changa1df8a92020-01-02 16:03:39 +08001935 ds.AddDir(PREREBOOT_DATA_DIR, false);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001936 add_mountinfo();
Peter Collingbourne78aa2942023-02-15 14:50:31 -08001937 for (const char* path : {"/proc/cpuinfo", "/proc/meminfo"}) {
1938 ds.AddZipEntry(ZIP_ROOT_DIR + path, path);
1939 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001940 DumpIpTablesAsRoot();
David Andersond9ba4752018-12-11 18:26:59 -08001941 DumpDynamicPartitionInfo();
Yifan Hong3945e1b2019-10-29 12:59:23 -07001942 ds.AddDir(OTA_METADATA_DIR, true);
Jeff Sharkey9df29d52023-02-06 14:26:30 -07001943 if (!PropertiesHelper::IsUserBuild()) {
1944 // Include dropbox entry files inside ZIP, but exclude
1945 // noisy WTF and StrictMode entries
1946 dump_files("", DROPBOX_DIR, skip_wtf_strictmode, _add_file_from_fd);
1947 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001948
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001949 // Capture any IPSec policies in play. No keys are exposed here.
Nandana Dutt4be45d12018-09-26 15:04:23 +01001950 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1951
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001952 // Dump IPsec stats. No keys are exposed here.
1953 DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
1954
Nandana Dutt4be45d12018-09-26 15:04:23 +01001955 // Run ss as root so we can see socket marks.
1956 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1957
1958 // Run iotop as root to show top 100 IO threads
1959 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1960
Erick Reyese68df822019-02-11 14:46:36 -08001961 // Gather shared memory buffer info if the product implements it
Hridya Valsaraju1da80c52021-01-09 22:10:11 -08001962 RunCommand("Dmabuf dump", {"dmabuf_dump"});
1963 RunCommand("Dmabuf per-buffer/per-exporter/per-device stats", {"dmabuf_dump", "-b"});
Erick Reyese68df822019-02-11 14:46:36 -08001964
Minchan Kim22c6a1e2019-09-30 15:58:10 -07001965 DumpFile("PSI cpu", "/proc/pressure/cpu");
1966 DumpFile("PSI memory", "/proc/pressure/memory");
1967 DumpFile("PSI io", "/proc/pressure/io");
1968
Steven Moreland9379c462023-12-21 02:04:27 +00001969 ds.AddZipEntry(ZIP_ROOT_DIR + KERNEL_CONFIG, KERNEL_CONFIG);
1970
MÃ¥rten Kongstad60195a72022-09-20 14:14:20 +02001971 RunCommand("SDK EXTENSIONS", {SDK_EXT_INFO, "--dump"},
1972 CommandOptions::WithTimeout(10).Always().DropRoot().Build());
1973
Rhed Jao5377d792020-07-16 17:37:39 +08001974 if (dump_pool_) {
1975 RETURN_IF_USER_DENIED_CONSENT();
Chris Morinbc223142022-02-04 14:17:11 -08001976 WaitForTask(std::move(dump_traces));
Rhed Jao5377d792020-07-16 17:37:39 +08001977
Chris Morinbc223142022-02-04 14:17:11 -08001978 // Current running thread in the pool is the root user also. Delete
1979 // the pool and make a new one later to ensure none of threads in the pool are root.
1980 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao5377d792020-07-16 17:37:39 +08001981 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001982 if (!DropRootUser()) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001983 return Dumpstate::RunStatus::ERROR;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001984 }
1985
Nandana Dutt5c390032019-03-12 10:52:56 +00001986 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttdb379fa2019-10-09 16:54:41 +01001987 Dumpstate::RunStatus status = dumpstate();
1988 // Capture logcat since the last time we did it.
1989 DoSystemLogcat(logcat_ts);
1990 return status;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001991}
1992
Rhed Jaob5685b32020-08-14 17:19:17 +08001993// Common states for telephony and wifi which are needed to be collected before
1994// dumpstate drop the root user.
1995static void DumpstateRadioAsRoot() {
1996 DumpIpTablesAsRoot();
1997 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1998}
1999
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002000// This method collects common dumpsys for telephony and wifi. Typically, wifi
2001// reports are fine to include all information, but telephony reports on user
2002// builds need to strip some content (see DumpstateTelephonyOnly).
2003static void DumpstateRadioCommon(bool include_sensitive_info = true) {
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002004 // We need to be picky about some stuff for telephony reports on user builds.
2005 if (!include_sensitive_info) {
2006 // Only dump the radio log buffer (other buffers and dumps contain too much unrelated info).
2007 DoRadioLogcat();
2008 } else {
Rhed Jaob5685b32020-08-14 17:19:17 +08002009 // DumpHals takes long time, post it to the another thread in the pool,
2010 // if pool is available.
Chris Morinbc223142022-02-04 14:17:11 -08002011 std::future<std::string> dump_hals;
Rhed Jaob5685b32020-08-14 17:19:17 +08002012 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002013 dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
Rhed Jaob5685b32020-08-14 17:19:17 +08002014 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002015 // Contains various system properties and process startup info.
2016 do_dmesg();
2017 // Logs other than the radio buffer may contain package/component names and potential PII.
2018 DoLogcat();
2019 // Too broad for connectivity problems.
2020 DoKmsg();
Rhed Jaob5685b32020-08-14 17:19:17 +08002021 // DumpHals contains unrelated hardware info (camera, NFC, biometrics, ...).
2022 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002023 WaitForTask(std::move(dump_hals));
Rhed Jaob5685b32020-08-14 17:19:17 +08002024 } else {
2025 RUN_SLOW_FUNCTION_AND_LOG(DUMP_HALS_TASK, DumpHals);
2026 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002027 }
2028
Jayachandran Ca94c7172017-06-10 15:08:12 -07002029 DumpPacketStats();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002030 DumpIpAddrAndRules();
2031 dump_route_tables();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002032 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
2033 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08002034}
2035
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002036// We use "telephony" here for legacy reasons, though this now really means "connectivity" (cellular
2037// + wifi + networking). This method collects dumpsys for connectivity debugging only. General rules
2038// for what can be included on user builds: all reported information MUST directly relate to
2039// connectivity debugging or customer support and MUST NOT contain unrelated personally identifiable
2040// information. This information MUST NOT identify user-installed packages (UIDs are OK, package
2041// names are not), and MUST NOT contain logs of user application traffic.
2042// TODO(b/148168577) rename this and other related fields/methods to "connectivity" instead.
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08002043static void DumpstateTelephonyOnly(const std::string& calling_package) {
mukesh agrawal253dad42018-01-23 21:59:59 -08002044 DurationReporter duration_reporter("DUMPSTATE");
Jichao Lie89d9c12019-11-21 19:02:51 -08002045
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002046 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
mukesh agrawal253dad42018-01-23 21:59:59 -08002047
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002048 const bool include_sensitive_info = !PropertiesHelper::IsUserBuild();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002049
Rhed Jaob5685b32020-08-14 17:19:17 +08002050 DumpstateRadioAsRoot();
2051 if (!DropRootUser()) {
2052 return;
2053 }
2054
2055 // Starts thread pool after the root user is dropped, and two additional threads
2056 // are created for DumpHals in the DumpstateRadioCommon and DumpstateBoard.
Chris Morinbc223142022-02-04 14:17:11 -08002057 std::future<std::string> dump_board;
Rhed Jaob5685b32020-08-14 17:19:17 +08002058 if (ds.dump_pool_) {
2059 ds.dump_pool_->start(/*thread_counts =*/2);
2060
2061 // DumpstateBoard takes long time, post it to the another thread in the pool,
2062 // if pool is available.
Chris Morinbc223142022-02-04 14:17:11 -08002063 dump_board = ds.dump_pool_->enqueueTaskWithFd(
2064 DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
Rhed Jaob5685b32020-08-14 17:19:17 +08002065 }
2066
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002067 DumpstateRadioCommon(include_sensitive_info);
2068
2069 if (include_sensitive_info) {
2070 // Contains too much unrelated PII, and given the unstructured nature of sysprops, we can't
2071 // really cherrypick all of the connectivity-related ones. Apps generally have no business
2072 // reading these anyway, and there should be APIs to supply the info in a more app-friendly
2073 // way.
2074 RunCommand("SYSTEM PROPERTIES", {"getprop"});
2075 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002076
2077 printf("========================================================\n");
2078 printf("== Android Framework Services\n");
2079 printf("========================================================\n");
2080
Vishnu Nair652cc802017-11-30 15:18:30 -08002081 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2082 SEC_TO_MSEC(10));
Hunter Knepshield31cbae12021-05-11 16:23:24 -07002083 RunDumpsys("DUMPSYS", {"vcn_management"}, CommandOptions::WithTimeout(90).Build(),
2084 SEC_TO_MSEC(10));
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08002085 if (include_sensitive_info) {
2086 // Carrier apps' services will be dumped below in dumpsys activity service all-non-platform.
2087 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
2088 SEC_TO_MSEC(10));
2089 } else {
2090 // If the caller is a carrier app and has a carrier service, dump it here since we aren't
2091 // running dumpsys activity service all-non-platform below. Due to the increased output, we
2092 // give a higher timeout as well.
2093 RunDumpsys("DUMPSYS", {"carrier_config", "--requesting-package", calling_package},
2094 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(30));
2095 }
2096 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002097 RunDumpsys("DUMPSYS", {"netpolicy"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2098 RunDumpsys("DUMPSYS", {"network_management"}, CommandOptions::WithTimeout(90).Build(),
Sooraj Sasindrane8d98912018-04-20 11:31:55 -07002099 SEC_TO_MSEC(10));
Hunter Knepshield0fe51b12020-03-05 16:58:20 -08002100 RunDumpsys("DUMPSYS", {"telephony.registry"}, CommandOptions::WithTimeout(90).Build(),
2101 SEC_TO_MSEC(10));
Jack Yu773cc032023-03-16 22:43:39 -07002102 RunDumpsys("DUMPSYS", {"isub"}, CommandOptions::WithTimeout(90).Build(),
2103 SEC_TO_MSEC(10));
Grant Menke56698972023-02-24 13:11:07 -08002104 RunDumpsys("DUMPSYS", {"telecom"}, CommandOptions::WithTimeout(90).Build(),
2105 SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002106 if (include_sensitive_info) {
2107 // Contains raw IP addresses, omit from reports on user builds.
2108 RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2109 // Contains raw destination IP/MAC addresses, omit from reports on user builds.
2110 RunDumpsys("DUMPSYS", {"connmetrics"}, CommandOptions::WithTimeout(90).Build(),
2111 SEC_TO_MSEC(10));
2112 // Contains package/component names, omit from reports on user builds.
2113 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
2114 SEC_TO_MSEC(10));
2115 // Contains package names, but should be relatively simple to remove them (also contains
2116 // UIDs already), omit from reports on user builds.
2117 RunDumpsys("BATTERYSTATS", {"deviceidle"}, CommandOptions::WithTimeout(90).Build(),
2118 SEC_TO_MSEC(10));
2119 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002120
2121 printf("========================================================\n");
2122 printf("== Running Application Services\n");
2123 printf("========================================================\n");
2124
2125 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
2126
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002127 if (include_sensitive_info) {
2128 printf("========================================================\n");
2129 printf("== Running Application Services (non-platform)\n");
2130 printf("========================================================\n");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002131
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002132 // Contains package/component names and potential PII, omit from reports on user builds.
2133 // To get dumps of the active CarrierService(s) on user builds, we supply an argument to the
2134 // carrier_config dumpsys instead.
2135 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
2136 DUMPSYS_COMPONENTS_OPTIONS);
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002137
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002138 printf("========================================================\n");
2139 printf("== Checkins\n");
2140 printf("========================================================\n");
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002141
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002142 // Contains package/component names, omit from reports on user builds.
2143 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
2144 }
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002145
2146 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07002147 printf("== dumpstate: done (id %d)\n", ds.id_);
2148 printf("========================================================\n");
Rhed Jaob5685b32020-08-14 17:19:17 +08002149
2150 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002151 WaitForTask(std::move(dump_board));
Rhed Jaob5685b32020-08-14 17:19:17 +08002152 } else {
2153 RUN_SLOW_FUNCTION_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
2154 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002155}
2156
mukesh agrawal253dad42018-01-23 21:59:59 -08002157// This method collects dumpsys for wifi debugging only
2158static void DumpstateWifiOnly() {
2159 DurationReporter duration_reporter("DUMPSTATE");
2160
Rhed Jaob5685b32020-08-14 17:19:17 +08002161 DumpstateRadioAsRoot();
2162 if (!DropRootUser()) {
2163 return;
2164 }
2165
2166 // Starts thread pool after the root user is dropped. Only one additional
2167 // thread is needed for DumpHals in the DumpstateRadioCommon.
2168 if (ds.dump_pool_) {
2169 ds.dump_pool_->start(/*thread_counts =*/1);
2170 }
2171
mukesh agrawal253dad42018-01-23 21:59:59 -08002172 DumpstateRadioCommon();
2173
2174 printf("========================================================\n");
2175 printf("== Android Framework Services\n");
2176 printf("========================================================\n");
2177
2178 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2179 SEC_TO_MSEC(10));
2180 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
2181 SEC_TO_MSEC(10));
2182
2183 printf("========================================================\n");
2184 printf("== dumpstate: done (id %d)\n", ds.id_);
2185 printf("========================================================\n");
2186}
2187
Elis Elliott8e401ad2023-08-08 11:18:59 +00002188// Collects a lightweight dumpstate to be used for debugging onboarding related flows.
2189static void DumpstateOnboardingOnly() {
2190 ds.AddDir(LOGPERSIST_DATA_DIR, false);
2191}
2192
Nandana Duttcf419a72019-03-14 10:40:17 +00002193Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
Gavin Corkery789d7a52021-02-24 23:52:35 +00002194 const std::string temp_file_pattern = ds.bugreport_internal_dir_ + "/dumptrace_XXXXXX";
Nandana Duttfaafd522019-03-11 09:23:09 +00002195 const size_t buf_size = temp_file_pattern.length() + 1;
2196 std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
2197 memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
2198
2199 // Create a new, empty file to receive all trace dumps.
2200 //
2201 // TODO: This can be simplified once we remove support for the old style
2202 // dumps. We can have a file descriptor passed in to dump_traces instead
2203 // of creating a file, closing it and then reopening it again.
2204 android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
2205 if (fd < 0) {
2206 MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002207 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002208 }
2209
2210 // Nobody should have access to this temporary file except dumpstate, but we
2211 // temporarily grant 'read' to 'others' here because this file is created
2212 // when tombstoned is still running as root, but dumped after dropping. This
2213 // can go away once support for old style dumping has.
2214 const int chmod_ret = fchmod(fd, 0666);
2215 if (chmod_ret < 0) {
2216 MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002217 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002218 }
2219
2220 std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
2221 if (proc.get() == nullptr) {
2222 MYLOGE("opendir /proc failed: %s\n", strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002223 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002224 }
2225
2226 // Number of times process dumping has timed out. If we encounter too many
2227 // failures, we'll give up.
2228 int timeout_failures = 0;
2229 bool dalvik_found = false;
2230
Jayant Chowdharya0a8eb22022-05-20 03:30:09 +00002231 const std::set<int> hal_pids = get_interesting_pids();
Nandana Duttfaafd522019-03-11 09:23:09 +00002232
2233 struct dirent* d;
2234 while ((d = readdir(proc.get()))) {
Nandana Duttcf419a72019-03-14 10:40:17 +00002235 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttfaafd522019-03-11 09:23:09 +00002236 int pid = atoi(d->d_name);
2237 if (pid <= 0) {
2238 continue;
2239 }
2240
Kevin Jeond0f8a982023-04-07 14:27:11 -04002241 // Skip cached processes.
2242 if (IsCached(pid)) {
2243 // For consistency, the header and footer to this message match those
2244 // dumped by debuggerd in the success case.
2245 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
2246 dprintf(fd, "Dump skipped for cached process.\n");
2247 dprintf(fd, "---- end %d ----", pid);
2248 continue;
2249 }
2250
Nandana Duttfaafd522019-03-11 09:23:09 +00002251 const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
2252 std::string exe;
2253 if (!android::base::Readlink(link_name, &exe)) {
2254 continue;
2255 }
2256
2257 bool is_java_process;
2258 if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
2259 // Don't bother dumping backtraces for the zygote.
2260 if (IsZygote(pid)) {
2261 continue;
2262 }
2263
2264 dalvik_found = true;
2265 is_java_process = true;
2266 } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
2267 is_java_process = false;
2268 } else {
2269 // Probably a native process we don't care about, continue.
2270 continue;
2271 }
2272
2273 // If 3 backtrace dumps fail in a row, consider debuggerd dead.
2274 if (timeout_failures == 3) {
2275 dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
2276 break;
2277 }
2278
2279 const uint64_t start = Nanotime();
2280 const int ret = dump_backtrace_to_file_timeout(
Kevin Jeonb8a39362023-04-04 15:00:34 -04002281 pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace, 3, fd);
Nandana Duttfaafd522019-03-11 09:23:09 +00002282
2283 if (ret == -1) {
2284 // For consistency, the header and footer to this message match those
2285 // dumped by debuggerd in the success case.
2286 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
2287 dprintf(fd, "Dump failed, likely due to a timeout.\n");
2288 dprintf(fd, "---- end %d ----", pid);
2289 timeout_failures++;
2290 continue;
2291 }
2292
2293 // We've successfully dumped stack traces, reset the failure count
2294 // and write a summary of the elapsed time to the file and continue with the
2295 // next process.
2296 timeout_failures = 0;
2297
2298 dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
2299 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
2300 }
2301
2302 if (!dalvik_found) {
2303 MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
2304 }
2305
Nandana Duttcf419a72019-03-14 10:40:17 +00002306 *path = file_name_buf.release();
2307 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002308}
2309
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002310static dumpstate_hal_hidl::DumpstateMode GetDumpstateHalModeHidl(
2311 const Dumpstate::BugreportMode bugreport_mode) {
2312 switch (bugreport_mode) {
2313 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2314 return dumpstate_hal_hidl::DumpstateMode::FULL;
2315 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2316 return dumpstate_hal_hidl::DumpstateMode::INTERACTIVE;
2317 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2318 return dumpstate_hal_hidl::DumpstateMode::REMOTE;
2319 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2320 return dumpstate_hal_hidl::DumpstateMode::WEAR;
2321 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2322 return dumpstate_hal_hidl::DumpstateMode::CONNECTIVITY;
2323 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2324 return dumpstate_hal_hidl::DumpstateMode::WIFI;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002325 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002326 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2327 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2328 }
2329 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2330}
2331
2332static dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode GetDumpstateHalModeAidl(
2333 const Dumpstate::BugreportMode bugreport_mode) {
2334 switch (bugreport_mode) {
2335 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2336 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::FULL;
2337 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2338 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::INTERACTIVE;
2339 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2340 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::REMOTE;
2341 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2342 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WEAR;
2343 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2344 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::CONNECTIVITY;
2345 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2346 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WIFI;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002347 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002348 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2349 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2350 }
2351 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2352}
2353
2354static void DoDumpstateBoardHidl(
2355 const sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_1_0,
2356 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2357 const Dumpstate::BugreportMode bugreport_mode,
2358 const size_t timeout_sec) {
2359
2360 using ScopedNativeHandle =
2361 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
2362 ScopedNativeHandle handle(native_handle_create(static_cast<int>(dumpstate_fds.size()), 0),
2363 [](native_handle_t* handle) {
2364 // we don't close file handle's here
2365 // via native_handle_close(handle)
2366 // instead we let dumpstate_fds close the file handles when
2367 // dumpstate_fds gets destroyed
2368 native_handle_delete(handle);
2369 });
2370 if (handle == nullptr) {
2371 MYLOGE("Could not create native_handle for dumpstate HAL\n");
2372 return;
2373 }
2374
2375 for (size_t i = 0; i < dumpstate_fds.size(); i++) {
2376 handle.get()->data[i] = dumpstate_fds[i].get();
2377 }
2378
2379 // Prefer version 1.1 if available. New devices launching with R are no longer allowed to
2380 // implement just 1.0.
2381 const char* descriptor_to_kill;
2382 using DumpstateBoardTask = std::packaged_task<bool()>;
2383 DumpstateBoardTask dumpstate_board_task;
2384 sp<dumpstate_hal_hidl::IDumpstateDevice> dumpstate_hal(
2385 dumpstate_hal_hidl::IDumpstateDevice::castFrom(dumpstate_hal_1_0));
2386 if (dumpstate_hal != nullptr) {
2387 MYLOGI("Using IDumpstateDevice v1.1 HIDL HAL");
2388
2389 dumpstate_hal_hidl::DumpstateMode dumpstate_hal_mode =
2390 GetDumpstateHalModeHidl(bugreport_mode);
2391
2392 descriptor_to_kill = dumpstate_hal_hidl::IDumpstateDevice::descriptor;
2393 dumpstate_board_task =
2394 DumpstateBoardTask([timeout_sec, dumpstate_hal_mode, dumpstate_hal, &handle]() -> bool {
2395 ::android::hardware::Return<dumpstate_hal_hidl::DumpstateStatus> status =
2396 dumpstate_hal->dumpstateBoard_1_1(handle.get(), dumpstate_hal_mode,
2397 SEC_TO_MSEC(timeout_sec));
2398 if (!status.isOk()) {
2399 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2400 return false;
2401 } else if (status != dumpstate_hal_hidl::DumpstateStatus::OK) {
2402 MYLOGE("dumpstateBoard failed with DumpstateStatus::%s\n",
2403 dumpstate_hal_hidl::toString(status).c_str());
2404 return false;
2405 }
2406 return true;
2407 });
2408 } else {
2409 MYLOGI("Using IDumpstateDevice v1.0 HIDL HAL");
2410
2411 descriptor_to_kill = dumpstate_hal_hidl_1_0::IDumpstateDevice::descriptor;
2412 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal_1_0, &handle]() -> bool {
2413 ::android::hardware::Return<void> status =
2414 dumpstate_hal_1_0->dumpstateBoard(handle.get());
2415 if (!status.isOk()) {
2416 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2417 return false;
2418 }
2419 return true;
2420 });
2421 }
2422 auto result = dumpstate_board_task.get_future();
2423 std::thread(std::move(dumpstate_board_task)).detach();
2424
2425 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2426 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2427 if (!android::base::SetProperty(
2428 "ctl.interface_restart",
2429 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2430 MYLOGE("Couldn't restart dumpstate HAL\n");
2431 }
2432 }
2433 // Wait some time for init to kill dumpstate vendor HAL
2434 constexpr size_t killing_timeout_sec = 10;
2435 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2436 MYLOGE(
2437 "killing dumpstateBoard timed out after %zus, continue and "
2438 "there might be racing in content\n",
2439 killing_timeout_sec);
2440 }
2441}
2442
2443static void DoDumpstateBoardAidl(
2444 const std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal,
2445 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2446 const Dumpstate::BugreportMode bugreport_mode, const size_t timeout_sec) {
2447 MYLOGI("Using IDumpstateDevice AIDL HAL");
2448
2449 const char* descriptor_to_kill;
2450 using DumpstateBoardTask = std::packaged_task<bool()>;
2451 DumpstateBoardTask dumpstate_board_task;
2452 dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode dumpstate_hal_mode =
2453 GetDumpstateHalModeAidl(bugreport_mode);
2454
2455 descriptor_to_kill = dumpstate_hal_aidl::IDumpstateDevice::descriptor;
2456 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal, &dumpstate_fds, dumpstate_hal_mode,
2457 timeout_sec]() -> bool {
2458 auto status = dumpstate_hal->dumpstateBoard(dumpstate_fds, dumpstate_hal_mode, timeout_sec);
2459
2460 if (!status.isOk()) {
2461 MYLOGE("dumpstateBoard failed: %s\n", status.getDescription().c_str());
2462 return false;
2463 }
2464 return true;
2465 });
2466 auto result = dumpstate_board_task.get_future();
2467 std::thread(std::move(dumpstate_board_task)).detach();
2468
2469 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2470 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2471 if (!android::base::SetProperty(
2472 "ctl.interface_restart",
2473 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2474 MYLOGE("Couldn't restart dumpstate HAL\n");
2475 }
2476 }
2477 // Wait some time for init to kill dumpstate vendor HAL
2478 constexpr size_t killing_timeout_sec = 10;
2479 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2480 MYLOGE(
2481 "killing dumpstateBoard timed out after %zus, continue and "
2482 "there might be racing in content\n",
2483 killing_timeout_sec);
2484 }
2485}
2486
2487static std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> GetDumpstateBoardAidlService() {
2488 const std::string aidl_instance_name =
2489 std::string(dumpstate_hal_aidl::IDumpstateDevice::descriptor) + "/default";
2490
2491 if (!AServiceManager_isDeclared(aidl_instance_name.c_str())) {
2492 return nullptr;
2493 }
2494
2495 ndk::SpAIBinder dumpstateBinder(AServiceManager_waitForService(aidl_instance_name.c_str()));
2496
2497 return dumpstate_hal_aidl::IDumpstateDevice::fromBinder(dumpstateBinder);
2498}
2499
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002500void Dumpstate::DumpstateBoard(int out_fd) {
2501 dprintf(out_fd, "========================================================\n");
2502 dprintf(out_fd, "== Board\n");
2503 dprintf(out_fd, "========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08002504
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002505 /*
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002506 * mount debugfs for non-user builds with ro.product.debugfs_restrictions.enabled
Hridya Valsaraju51101602021-04-02 14:32:46 -07002507 * set to true and unmount it after invoking dumpstateBoard_* methods.
2508 * This is to enable debug builds to not have debugfs mounted during runtime.
2509 * It will also ensure that debugfs is only accessed by the dumpstate HAL.
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002510 */
Hridya Valsaraju51101602021-04-02 14:32:46 -07002511 auto mount_debugfs =
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002512 android::base::GetBoolProperty("ro.product.debugfs_restrictions.enabled", false);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002513 if (mount_debugfs) {
2514 RunCommand("mount debugfs", {"mount", "-t", "debugfs", "debugfs", "/sys/kernel/debug"},
2515 AS_ROOT_20);
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002516 RunCommand("chmod debugfs", {"chmod", "0755", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002517 }
2518
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002519 std::vector<std::string> paths;
2520 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07002521 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002522 paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
2523 kDumpstateBoardFiles[i].c_str()));
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002524 remover.emplace_back(android::base::make_scope_guard(
2525 std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002526 }
Jie Song9fbfad02017-06-20 16:29:42 -07002527
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002528 // get dumpstate HAL AIDL implementation
2529 std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal_handle_aidl(
2530 GetDumpstateBoardAidlService());
2531 if (dumpstate_hal_handle_aidl == nullptr) {
2532 MYLOGI("No IDumpstateDevice AIDL implementation\n");
2533 }
2534
2535 // get dumpstate HAL HIDL implementation, only if AIDL HAL implementation not found
2536 sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_handle_hidl_1_0 = nullptr;
2537 if (dumpstate_hal_handle_aidl == nullptr) {
2538 dumpstate_hal_handle_hidl_1_0 = dumpstate_hal_hidl_1_0::IDumpstateDevice::getService();
2539 if (dumpstate_hal_handle_hidl_1_0 == nullptr) {
2540 MYLOGI("No IDumpstateDevice HIDL implementation\n");
2541 }
2542 }
2543
2544 // if neither HIDL nor AIDL implementation found, then return
2545 if (dumpstate_hal_handle_hidl_1_0 == nullptr && dumpstate_hal_handle_aidl == nullptr) {
2546 MYLOGE("Could not find IDumpstateDevice implementation\n");
Wei Wang587eac92018-04-05 12:17:20 -07002547 return;
2548 }
2549
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002550 // this is used to hold the file descriptors and when this variable goes out of scope
2551 // the file descriptors are closed
2552 std::vector<::ndk::ScopedFileDescriptor> dumpstate_fds;
Wei Wang587eac92018-04-05 12:17:20 -07002553
Nandana Dutt5c390032019-03-12 10:52:56 +00002554 // TODO(128270426): Check for consent in between?
Wei Wang587eac92018-04-05 12:17:20 -07002555 for (size_t i = 0; i < paths.size(); i++) {
2556 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
2557
2558 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
2559 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
2560 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
2561 if (fd < 0) {
2562 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
2563 return;
2564 }
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002565
2566 dumpstate_fds.emplace_back(fd.release());
2567 // we call fd.release() here to make sure "fd" does not get closed
2568 // after "fd" goes out of scope after this block.
2569 // "fd" will be closed when "dumpstate_fds" goes out of scope
2570 // i.e. when we exit this function
Wei Wang587eac92018-04-05 12:17:20 -07002571 }
2572
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002573 // Given that bugreport is required to diagnose failures, it's better to set an arbitrary amount
2574 // of timeout for IDumpstateDevice than to block the rest of bugreport. In the timeout case, we
2575 // will kill the HAL and grab whatever it dumped in time.
Michael Eastwood8523ea02022-03-10 16:33:08 -08002576 constexpr size_t timeout_sec = 45;
Wei Wang587eac92018-04-05 12:17:20 -07002577
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002578 if (dumpstate_hal_handle_aidl != nullptr) {
2579 DoDumpstateBoardAidl(dumpstate_hal_handle_aidl, dumpstate_fds, options_->bugreport_mode,
2580 timeout_sec);
2581 } else if (dumpstate_hal_handle_hidl_1_0 != nullptr) {
2582 // run HIDL HAL only if AIDL HAL not found
2583 DoDumpstateBoardHidl(dumpstate_hal_handle_hidl_1_0, dumpstate_fds, options_->bugreport_mode,
2584 timeout_sec);
Wei Wang587eac92018-04-05 12:17:20 -07002585 }
2586
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002587 if (mount_debugfs) {
Hridya Valsaraju51101602021-04-02 14:32:46 -07002588 auto keep_debugfs_mounted =
2589 android::base::GetProperty("persist.dbg.keep_debugfs_mounted", "");
2590 if (keep_debugfs_mounted.empty())
2591 RunCommand("unmount debugfs", {"umount", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002592 }
2593
Wei Wang587eac92018-04-05 12:17:20 -07002594 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
2595 for (size_t i = 0; i < paths.size(); i++) {
2596 struct stat s;
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002597 if (fstat(dumpstate_fds[i].get(), &s) == -1) {
2598 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(), strerror(errno));
Wei Wang587eac92018-04-05 12:17:20 -07002599 file_sizes[i] = -1;
2600 continue;
2601 }
2602 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002603 }
2604
2605 for (size_t i = 0; i < paths.size(); i++) {
2606 if (file_sizes[i] == -1) {
2607 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002608 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002609 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07002610 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002611 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002612 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002613 remover[i].Disable();
2614 EnqueueAddZipEntryAndCleanupIfNeeded(kDumpstateBoardFiles[i], paths[i]);
2615 dprintf(out_fd, "*** See %s entry ***\n", kDumpstateBoardFiles[i].c_str());
Jie Song9fbfad02017-06-20 16:29:42 -07002616 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08002617}
2618
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002619static void ShowUsage() {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002620 fprintf(stderr,
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002621 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o directory] [-p] "
2622 "[-s] [-S] [-q] [-P] [-R] [-L] [-V version]\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002623 " -h: display this help message\n"
2624 " -b: play sound file instead of vibrate, at beginning of job\n"
2625 " -e: play sound file instead of vibrate, at end of job\n"
mhasank2d75c442020-06-11 15:05:25 -07002626 " -o: write to custom directory (only in limited mode)\n"
Abhijeet Kaurbb55a3b2019-06-13 18:07:25 +01002627 " -p: capture screenshot to filename.png\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002628 " -s: write zipped file to control socket (for init)\n"
2629 " -S: write file location to control socket (for init)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002630 " -q: disable vibrate\n"
Abhijeet Kaure370d682019-10-01 16:49:30 +01002631 " -P: send broadcast when started and do progress updates\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002632 " -R: take bugreport in remote mode (shouldn't be used with -P)\n"
Nandana Dutt235864b2019-01-22 12:10:16 +00002633 " -w: start binder service and make it wait for a call to startBugreport\n"
mhasankd451a472020-05-26 18:02:39 -07002634 " -L: output limited information that is safe for submission in feedback reports\n"
Felipe Lemed071c682016-10-20 16:48:00 -07002635 " -v: prints the dumpstate header and exit\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002636}
2637
Wei Liuf87959e2016-08-26 14:51:42 -07002638static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07002639 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07002640}
2641
Felipe Leme1d486fe2016-10-14 18:06:47 -07002642bool Dumpstate::FinishZipFile() {
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002643 // Runs all enqueued adding zip entry and cleanup tasks before finishing the zip file.
2644 if (zip_entry_tasks_) {
2645 zip_entry_tasks_->run(/* do_cancel = */false);
2646 }
2647
Felipe Leme9a523ae2016-10-20 15:10:33 -07002648 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07002649 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07002650 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002651 // Final timestamp
2652 char date[80];
2653 time_t the_real_now_please_stand_up = time(nullptr);
2654 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002655 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002656 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002657
Felipe Leme9a523ae2016-10-20 15:10:33 -07002658 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002659 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08002660 return false;
2661 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07002662 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002663 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08002664 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08002665 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08002666
Felipe Leme0f3fb202016-06-10 17:10:53 -07002667 // Add log file (which contains stderr output) to zip...
2668 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002669 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07002670 MYLOGE("Failed to add dumpstate log to .zip file\n");
2671 return false;
2672 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002673 // TODO: Should truncate the existing file.
2674 // ... and re-open it for further logging.
Nandana Dutta344cb62019-02-22 15:12:35 +00002675 if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
2676 return false;
2677 }
Felipe Leme0f3fb202016-06-10 17:10:53 -07002678 fprintf(stderr, "\n");
2679
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002680 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07002681 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002682 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002683 return false;
2684 }
2685
Felipe Leme1d486fe2016-10-14 18:06:47 -07002686 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
2687 ds.zip_file.reset(nullptr);
2688
Felipe Lemee9d2c542016-11-15 11:48:26 -08002689 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002690 android::os::UnlinkAndLogOnError(tmp_path_);
Felipe Lemec4eee562016-04-21 15:42:55 -07002691
Felipe Leme1e9edc62015-12-21 16:02:13 -08002692 return true;
2693}
Felipe Leme6e01fa62015-11-11 19:35:14 -08002694
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00002695static void SendBroadcast(const std::string& action,
2696 const std::vector<std::string>& args,
2697 int32_t user_id) {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002698 // clang-format off
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00002699 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user",
2700 std::to_string(user_id), "--receiver-foreground",
2701 "--receiver-include-background", "-a", action};
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002702 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08002703
2704 am.insert(am.end(), args.begin(), args.end());
2705
Felipe Leme8d2410e2017-02-08 09:46:08 -08002706 RunCommand("", am,
2707 CommandOptions::WithTimeout(20)
2708 .Log("Sending broadcast: '%s'\n")
2709 .Always()
2710 .DropRoot()
2711 .RedirectStderr()
2712 .Build());
2713}
2714
Felipe Leme35b8cf12017-02-10 15:47:29 -08002715static void Vibrate(int duration_ms) {
2716 // clang-format off
Lais Andrade51156962021-02-22 19:21:35 +00002717 std::vector<std::string> args = {"cmd", "vibrator_manager", "synced", "-f", "-d", "dumpstate",
2718 "oneshot", std::to_string(duration_ms)};
2719 RunCommand("", args,
Felipe Leme35b8cf12017-02-10 15:47:29 -08002720 CommandOptions::WithTimeout(10)
2721 .Log("Vibrate: '%s'\n")
2722 .Always()
2723 .Build());
2724 // clang-format on
2725}
2726
Nandana Dutt979388e2018-11-30 16:48:55 +00002727static void MaybeResolveSymlink(std::string* path) {
2728 std::string resolved_path;
2729 if (android::base::Readlink(*path, &resolved_path)) {
2730 *path = resolved_path;
2731 }
2732}
2733
Nandana Dutt4be45d12018-09-26 15:04:23 +01002734/*
2735 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002736 * and adds the version file. Return false if zip_file could not be open to write.
Nandana Dutt4be45d12018-09-26 15:04:23 +01002737 */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002738static bool PrepareToWriteToFile() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002739 MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2740
Nandana Dutt4be45d12018-09-26 15:04:23 +01002741 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2742 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002743 ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002744 char date[80];
2745 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2746 ds.name_ = date;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002747
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002748 if (ds.options_->telephony_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002749 ds.base_name_ += "-telephony";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002750 } else if (ds.options_->wifi_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002751 ds.base_name_ += "-wifi";
2752 }
2753
Paul Chang0d2aad72020-02-13 20:04:03 +08002754 if (ds.options_->do_screenshot) {
Nandana Dutt9d17b942020-03-26 10:02:59 +00002755 ds.screenshot_path_ = ds.GetPath(ds.CalledByApi() ? "-png.tmp" : ".png");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002756 }
2757 ds.tmp_path_ = ds.GetPath(".tmp");
2758 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2759
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01002760 std::string destination = ds.CalledByApi()
Nandana Dutt54dbd672019-01-11 12:58:05 +00002761 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
Nandana Dutt9a76d202019-01-21 15:56:48 +00002762 : ds.bugreport_internal_dir_.c_str();
Nandana Dutt4be45d12018-09-26 15:04:23 +01002763 MYLOGD(
Nandana Dutt235c6672019-11-14 15:22:32 +00002764 "Bugreport dir: [%s] "
2765 "Base name: [%s] "
2766 "Suffix: [%s] "
2767 "Log path: [%s] "
2768 "Temporary path: [%s] "
2769 "Screenshot path: [%s]\n",
Nandana Dutt9a76d202019-01-21 15:56:48 +00002770 destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2771 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002772
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002773 ds.path_ = ds.GetPath(ds.CalledByApi() ? "-zip.tmp" : ".zip");
2774 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2775 create_parent_dirs(ds.path_.c_str());
2776 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2777 if (ds.zip_file == nullptr) {
2778 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2779 return false;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002780 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002781 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2782 ds.AddTextZipEntry("version.txt", ds.version_);
2783 return true;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002784}
2785
2786/*
Abhijeet Kaure370d682019-10-01 16:49:30 +01002787 * Finalizes writing to the file by zipping the tmp file to the final location,
Nandana Dutt4be45d12018-09-26 15:04:23 +01002788 * printing zipped file status, etc.
2789 */
2790static void FinalizeFile() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002791 bool do_text_file = !ds.FinishZipFile();
2792 if (do_text_file) {
2793 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002794 }
mhasank2d75c442020-06-11 15:05:25 -07002795
2796 std::string final_path = ds.path_;
2797 if (ds.options_->OutputToCustomFile()) {
mhasank3a4cfb42020-06-15 18:06:43 -07002798 final_path = ds.GetPath(ds.options_->out_dir, ".zip");
mhasank2d75c442020-06-11 15:05:25 -07002799 android::os::CopyFileToFile(ds.path_, final_path);
2800 }
2801
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002802 if (ds.options_->stream_to_socket) {
2803 android::os::CopyFileToFd(ds.path_, ds.control_socket_fd_);
2804 } else if (ds.options_->progress_updates_to_socket) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002805 if (do_text_file) {
2806 dprintf(ds.control_socket_fd_,
2807 "FAIL:could not create zip file, check %s "
2808 "for more details\n",
2809 ds.log_path_.c_str());
2810 } else {
mhasank2d75c442020-06-11 15:05:25 -07002811 dprintf(ds.control_socket_fd_, "OK:%s\n", final_path.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002812 }
2813 }
2814}
2815
Nandana Dutt4be45d12018-09-26 15:04:23 +01002816
Nandana Dutt58d72e22018-11-16 10:30:48 +00002817static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2818 switch (mode) {
2819 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2820 return "BUGREPORT_FULL";
2821 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2822 return "BUGREPORT_INTERACTIVE";
2823 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2824 return "BUGREPORT_REMOTE";
2825 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2826 return "BUGREPORT_WEAR";
2827 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2828 return "BUGREPORT_TELEPHONY";
2829 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2830 return "BUGREPORT_WIFI";
Elis Elliott8e401ad2023-08-08 11:18:59 +00002831 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
2832 return "BUGREPORT_ONBOARDING";
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002833 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2834 return "BUGREPORT_DEFAULT";
Nandana Dutt58d72e22018-11-16 10:30:48 +00002835 }
2836}
2837
Steven Leeb573eb82022-11-29 22:31:35 +08002838static bool IsConsentlessBugreportAllowed(const Dumpstate::DumpOptions& options) {
2839 // only BUGREPORT_TELEPHONY does not allow using consentless bugreport
2840 return !options.telephony_only;
2841}
2842
Paul Changf59c2b72020-03-10 02:08:55 +08002843static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options,
2844 bool is_screenshot_requested) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002845 // Modify com.android.shell.BugreportProgressService#isDefaultScreenshotRequired as well for
2846 // default system screenshots.
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002847 options->bugreport_mode = mode;
2848 options->bugreport_mode_string = ModeToString(mode);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002849 switch (mode) {
2850 case Dumpstate::BugreportMode::BUGREPORT_FULL:
Paul Changf59c2b72020-03-10 02:08:55 +08002851 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002852 break;
2853 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002854 // Currently, the dumpstate binder is only used by Shell to update progress.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002855 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002856 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002857 break;
2858 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002859 options->do_vibrate = false;
2860 options->is_remote_mode = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002861 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002862 break;
2863 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
Robert Ginda55ecebd2023-04-03 22:53:13 +00002864 options->do_vibrate = false;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002865 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002866 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002867 break;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002868 // TODO(b/148168577) rename TELEPHONY everywhere to CONNECTIVITY.
Nandana Dutt58d72e22018-11-16 10:30:48 +00002869 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002870 options->telephony_only = true;
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002871 options->do_progress_updates = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002872 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002873 break;
2874 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002875 options->wifi_only = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002876 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002877 break;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002878 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
2879 options->onboarding_only = true;
2880 options->do_screenshot = false;
2881 break;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002882 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2883 break;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002884 }
2885}
2886
Nandana Dutt58d72e22018-11-16 10:30:48 +00002887static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
Nandana Dutt235c6672019-11-14 15:22:32 +00002888 MYLOGI(
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002889 "do_vibrate: %d stream_to_socket: %d progress_updates_to_socket: %d do_screenshot: %d "
Rhed Jao25f50e02020-08-20 00:10:32 +08002890 "is_remote_mode: %d show_header_only: %d telephony_only: %d "
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002891 "wifi_only: %d do_progress_updates: %d fd: %d bugreport_mode: %s "
mhasankd451a472020-05-26 18:02:39 -07002892 "limited_only: %d args: %s\n",
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002893 options.do_vibrate, options.stream_to_socket, options.progress_updates_to_socket,
Paul Chang0d2aad72020-02-13 20:04:03 +08002894 options.do_screenshot, options.is_remote_mode, options.show_header_only,
Rhed Jao25f50e02020-08-20 00:10:32 +08002895 options.telephony_only, options.wifi_only,
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002896 options.do_progress_updates, options.bugreport_fd.get(),
2897 options.bugreport_mode_string.c_str(),
2898 options.limited_only, options.args.c_str());
Nandana Dutt58d72e22018-11-16 10:30:48 +00002899}
2900
Nandana Dutt54dbd672019-01-11 12:58:05 +00002901void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
Kean Mariotti306633e2022-09-05 16:30:47 +00002902 int bugreport_flags,
Nandana Dutt54dbd672019-01-11 12:58:05 +00002903 const android::base::unique_fd& bugreport_fd_in,
Paul Changf59c2b72020-03-10 02:08:55 +08002904 const android::base::unique_fd& screenshot_fd_in,
Kholoud Mohameddef4e432024-05-15 12:47:46 +00002905 bool is_screenshot_requested,
2906 bool skip_user_consent) {
Kean Mariotti306633e2022-09-05 16:30:47 +00002907 this->use_predumped_ui_data = bugreport_flags & BugreportFlag::BUGREPORT_USE_PREDUMPED_UI_DATA;
Gavin Corkerya44686c2022-11-23 18:16:51 +00002908 this->is_consent_deferred = bugreport_flags & BugreportFlag::BUGREPORT_FLAG_DEFER_CONSENT;
Kholoud Mohameddef4e432024-05-15 12:47:46 +00002909 this->skip_user_consent = skip_user_consent;
Nandana Dutt54dbd672019-01-11 12:58:05 +00002910 // Duplicate the fds because the passed in fds don't outlive the binder transaction.
Todd Frederick621533f2022-03-26 02:54:17 +00002911 bugreport_fd.reset(fcntl(bugreport_fd_in.get(), F_DUPFD_CLOEXEC, 0));
2912 screenshot_fd.reset(fcntl(screenshot_fd_in.get(), F_DUPFD_CLOEXEC, 0));
Nandana Dutt58d72e22018-11-16 10:30:48 +00002913
Paul Changf59c2b72020-03-10 02:08:55 +08002914 SetOptionsFromMode(bugreport_mode, this, is_screenshot_requested);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002915}
2916
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002917Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
2918 RunStatus status = RunStatus::OK;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002919 int c;
mhasankd451a472020-05-26 18:02:39 -07002920 while ((c = getopt(argc, argv, "dho:svqzpLPBRSV:w")) != -1) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002921 switch (c) {
2922 // clang-format off
mhasank3a4cfb42020-06-15 18:06:43 -07002923 case 'o': out_dir = optarg; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002924 case 's': stream_to_socket = true; break;
2925 case 'S': progress_updates_to_socket = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002926 case 'v': show_header_only = true; break;
2927 case 'q': do_vibrate = false; break;
Paul Chang0d2aad72020-02-13 20:04:03 +08002928 case 'p': do_screenshot = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002929 case 'P': do_progress_updates = true; break;
2930 case 'R': is_remote_mode = true; break;
mhasankd451a472020-05-26 18:02:39 -07002931 case 'L': limited_only = true; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002932 case 'V':
2933 case 'd':
2934 case 'z':
2935 // compatibility no-op
2936 break;
Nandana Dutt235864b2019-01-22 12:10:16 +00002937 case 'w':
2938 // This was already processed
2939 break;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002940 case 'h':
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002941 status = RunStatus::HELP;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002942 break;
2943 default:
2944 fprintf(stderr, "Invalid option: %c\n", c);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002945 status = RunStatus::INVALID_INPUT;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002946 break;
2947 // clang-format on
2948 }
2949 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08002950
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002951 for (int i = 0; i < argc; i++) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002952 args += argv[i];
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002953 if (i < argc - 1) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002954 args += " ";
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002955 }
2956 }
2957
2958 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
2959 optind = 1;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002960
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002961 return status;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002962}
2963
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002964bool Dumpstate::DumpOptions::ValidateOptions() const {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002965 if (bugreport_fd.get() != -1 && stream_to_socket) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002966 return false;
2967 }
2968
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002969 if ((progress_updates_to_socket || do_progress_updates) && stream_to_socket) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002970 return false;
2971 }
2972
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002973 if (is_remote_mode && (do_progress_updates || stream_to_socket)) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002974 return false;
2975 }
2976 return true;
2977}
2978
Nandana Dutt197661d2018-11-16 16:40:21 +00002979void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
2980 options_ = std::move(options);
2981}
2982
Abhijeet Kaura407fb82020-03-27 12:51:12 +00002983void Dumpstate::Initialize() {
2984 /* gets the sequential id */
2985 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
2986 id_ = ++last_id;
2987 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
2988}
2989
Nandana Duttd2f5f082019-01-18 17:13:52 +00002990Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
2991 Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
Gavin Corkerya44686c2022-11-23 18:16:51 +00002992 HandleRunStatus(status);
2993 return status;
2994}
2995
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00002996Dumpstate::RunStatus Dumpstate::Retrieve(int32_t calling_uid, const std::string& calling_package,
Kholoud Mohameddef4e432024-05-15 12:47:46 +00002997 const bool keep_bugreport_on_retrieval,
2998 const bool skip_user_consent) {
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00002999 Dumpstate::RunStatus status = RetrieveInternal(calling_uid, calling_package,
Kholoud Mohameddef4e432024-05-15 12:47:46 +00003000 keep_bugreport_on_retrieval,
3001 skip_user_consent);
Gavin Corkerya44686c2022-11-23 18:16:51 +00003002 HandleRunStatus(status);
3003 return status;
3004}
3005
3006Dumpstate::RunStatus Dumpstate::RetrieveInternal(int32_t calling_uid,
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003007 const std::string& calling_package,
Kholoud Mohameddef4e432024-05-15 12:47:46 +00003008 const bool keep_bugreport_on_retrieval,
3009 const bool skip_user_consent) {
3010 if (!android::app::admin::flags::onboarding_consentless_bugreports() || !skip_user_consent) {
3011 consent_callback_ = new ConsentCallback();
3012 const String16 incidentcompanion("incidentcompanion");
3013 sp<android::IBinder> ics(
3014 defaultServiceManager()->checkService(incidentcompanion));
3015 android::String16 package(calling_package.c_str());
3016 if (ics != nullptr) {
3017 MYLOGD("Checking user consent via incidentcompanion service\n");
3018
3019 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
3020 calling_uid, package, String16(), String16(),
3021 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
3022 } else {
3023 MYLOGD(
3024 "Unable to check user consent; incidentcompanion service unavailable\n");
3025 return RunStatus::USER_CONSENT_TIMED_OUT;
3026 }
3027 UserConsentResult consent_result = consent_callback_->getResult();
3028 int timeout_ms = 30 * 1000;
3029 while (consent_result == UserConsentResult::UNAVAILABLE &&
3030 consent_callback_->getElapsedTimeMs() < timeout_ms) {
3031 sleep(1);
3032 consent_result = consent_callback_->getResult();
3033 }
3034 if (consent_result == UserConsentResult::DENIED) {
3035 return RunStatus::USER_CONSENT_DENIED;
3036 }
3037 if (consent_result == UserConsentResult::UNAVAILABLE) {
3038 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3039 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3040 consent_callback_.get());
3041 return RunStatus::USER_CONSENT_TIMED_OUT;
3042 }
Gavin Corkerya44686c2022-11-23 18:16:51 +00003043 }
3044
3045 bool copy_succeeded =
3046 android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003047
3048 if (copy_succeeded && (!android::app::admin::flags::onboarding_bugreport_v2_enabled()
3049 || !keep_bugreport_on_retrieval)) {
3050 android::os::UnlinkAndLogOnError(path_);
Gavin Corkerya44686c2022-11-23 18:16:51 +00003051 }
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003052
Gavin Corkerya44686c2022-11-23 18:16:51 +00003053 return copy_succeeded ? Dumpstate::RunStatus::OK
3054 : Dumpstate::RunStatus::ERROR;
3055}
3056
3057void Dumpstate::HandleRunStatus(Dumpstate::RunStatus status) {
3058 if (listener_ != nullptr) {
Nandana Duttbabf6c72019-01-15 14:11:12 +00003059 switch (status) {
3060 case Dumpstate::RunStatus::OK:
Gavin Corkerya44686c2022-11-23 18:16:51 +00003061 listener_->onFinished(path_.c_str());
Nandana Duttbabf6c72019-01-15 14:11:12 +00003062 break;
3063 case Dumpstate::RunStatus::HELP:
3064 break;
3065 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003066 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00003067 break;
3068 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003069 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
3070 break;
3071 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3072 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
3073 break;
3074 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
3075 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00003076 break;
3077 }
3078 }
Nandana Duttbabf6c72019-01-15 14:11:12 +00003079}
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003080void Dumpstate::Cancel() {
3081 CleanupTmpFiles();
3082 android::os::UnlinkAndLogOnError(log_path_);
3083 for (int i = 0; i < NUM_OF_DUMPS; i++) {
3084 android::os::UnlinkAndLogOnError(ds.bugreport_internal_dir_ + "/" +
3085 kDumpstateBoardFiles[i]);
3086 }
3087 tombstone_data_.clear();
3088 anr_data_.clear();
Andy Hungd62f7e62024-01-11 15:47:52 -08003089 anr_trace_data_.clear();
Woody Lin20767a92022-11-29 15:50:24 +08003090 shutdown_checkpoints_.clear();
Rhed Jao0daac912020-08-21 14:48:20 +08003091
3092 // Instead of shutdown the pool, we delete temporary files directly since
3093 // shutdown blocking the call.
3094 if (dump_pool_) {
3095 dump_pool_->deleteTempFiles();
3096 }
3097 if (zip_entry_tasks_) {
3098 zip_entry_tasks_->run(/*do_cancel =*/ true);
3099 }
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003100}
3101
Kean Mariotti306633e2022-09-05 16:30:47 +00003102void Dumpstate::PreDumpUiData() {
Kean Mariottica20f2d2023-12-15 09:34:25 +00003103 auto snapshot_system_trace = MaybeSnapshotSystemTraceAsync();
Kean Mariotti306633e2022-09-05 16:30:47 +00003104 MaybeSnapshotUiTraces();
Kean Mariottica20f2d2023-12-15 09:34:25 +00003105 MaybeWaitForSnapshotSystemTrace(std::move(snapshot_system_trace));
Kean Mariotti306633e2022-09-05 16:30:47 +00003106}
3107
Nandana Dutt979388e2018-11-30 16:48:55 +00003108/*
3109 * Dumps relevant information to a bugreport based on the given options.
3110 *
3111 * The bugreport can be dumped to a file or streamed to a socket.
3112 *
3113 * How dumping to file works:
3114 * stdout is redirected to a temporary file. This will later become the main bugreport entry.
3115 * stderr is redirected a log file.
3116 *
3117 * The temporary bugreport is then populated via printfs, dumping contents of files and
3118 * output of commands to stdout.
3119 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003120 * A bunch of other files and dumps are added to the zip archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00003121 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003122 * The temporary bugreport file and the log file also get added to the archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00003123 *
mhasank2d75c442020-06-11 15:05:25 -07003124 * Bugreports are first generated in a local directory and later copied to the caller's fd
3125 * or directory if supplied.
Nandana Dutt979388e2018-11-30 16:48:55 +00003126 */
Nandana Duttd2f5f082019-01-18 17:13:52 +00003127Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
3128 const std::string& calling_package) {
Rhed Jao5377d792020-07-16 17:37:39 +08003129 DurationReporter duration_reporter("RUN INTERNAL", /* logcat_only = */true);
Nandana Dutt979388e2018-11-30 16:48:55 +00003130 LogDumpOptions(*options_);
Nandana Dutt197661d2018-11-16 16:40:21 +00003131 if (!options_->ValidateOptions()) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00003132 MYLOGE("Invalid options specified\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003133 return RunStatus::INVALID_INPUT;
3134 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003135 /* set as high priority, and protect from OOM killer */
3136 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003137
Felipe Lemed071c682016-10-20 16:48:00 -07003138 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07003139 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003140 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003141 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003142 } else {
3143 /* fallback to kernels <= 2.6.35 */
3144 oom_adj = fopen("/proc/self/oom_adj", "we");
3145 if (oom_adj) {
3146 fputs("-17", oom_adj);
3147 fclose(oom_adj);
3148 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003149 }
3150
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003151 if (version_ == VERSION_DEFAULT) {
3152 version_ = VERSION_CURRENT;
Michal Karpinski4db754f2015-12-11 18:04:32 +00003153 }
3154
Chris Morin5a50d482022-02-01 17:41:18 -08003155 if (version_ != VERSION_CURRENT) {
3156 MYLOGE("invalid version requested ('%s'); supported values are: ('%s', '%s')\n",
3157 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003158 return RunStatus::INVALID_INPUT;
Felipe Lemed071c682016-10-20 16:48:00 -07003159 }
3160
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003161 if (options_->show_header_only) {
3162 PrintHeader();
3163 return RunStatus::OK;
Felipe Lemed071c682016-10-20 16:48:00 -07003164 }
3165
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003166 MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n",
3167 calling_uid, calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003168
Felipe Leme7447d7c2016-11-03 18:12:22 -07003169 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003170 std::string stats_path =
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003171 android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003172 progress_.reset(new Progress(stats_path));
Felipe Leme7447d7c2016-11-03 18:12:22 -07003173
Sahana Raof35ed432019-07-12 10:47:52 +01003174 if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
3175 MYLOGE("Failed to acquire wake lock: %s\n", strerror(errno));
3176 } else {
3177 // Wake lock will be released automatically on process death
3178 MYLOGD("Wake lock acquired.\n");
3179 }
3180
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08003181 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07003182
Felipe Lemef0292972016-11-22 13:57:05 -08003183 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07003184 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
3185 }
3186
Kevin Jeonfa64e642023-07-27 11:36:41 -04003187 if (PropertiesHelper::IsStrictRun()) {
3188 MYLOGI(
3189 "Running on strict-run mode, which has shorter timeouts "
3190 "(to disable, call 'setprop dumpstate.strict_run false')\n");
3191 }
3192
Nandana Dutt235c6672019-11-14 15:22:32 +00003193 MYLOGI("dumpstate info: id=%d, args='%s', bugreport_mode= %s bugreport format version: %s\n",
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00003194 id_, options_->args.c_str(), options_->bugreport_mode_string.c_str(), version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08003195
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003196 do_early_screenshot_ = options_->do_progress_updates;
Felipe Lemee338bf62015-12-07 14:03:50 -08003197
Christopher Ferrised9354f2014-10-01 17:35:01 -07003198 // If we are going to use a socket, do it as early as possible
3199 // to avoid timeouts from bugreport.
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003200 if (options_->stream_to_socket || options_->progress_updates_to_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07003201 MYLOGD("Opening control socket\n");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003202 control_socket_fd_ = open_socket_fn_("dumpstate");
Nandana Dutta344cb62019-02-22 15:12:35 +00003203 if (control_socket_fd_ == -1) {
3204 return ERROR;
3205 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003206 if (options_->progress_updates_to_socket) {
3207 options_->do_progress_updates = 1;
3208 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07003209 }
3210
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003211 if (!PrepareToWriteToFile()) {
3212 return ERROR;
3213 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08003214
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003215 // Interactive, wear & telephony modes are default to true.
3216 // and may enable from cli option or when using control socket
3217 if (options_->do_progress_updates) {
3218 // clang-format off
3219 std::vector<std::string> am_args = {
3220 "--receiver-permission", "android.permission.DUMP",
3221 };
3222 // clang-format on
3223 // Send STARTED broadcast for apps that listen to bugreport generation events
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003224 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED",
3225 am_args, multiuser_get_user_id(calling_uid));
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003226 if (options_->progress_updates_to_socket) {
3227 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08003228 }
3229 }
3230
Nick Kralevichf3599b32016-01-25 15:05:16 -08003231 /* read /proc/cmdline before dropping root */
3232 FILE *cmdline = fopen("/proc/cmdline", "re");
3233 if (cmdline) {
3234 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
3235 fclose(cmdline);
3236 }
3237
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003238 if (options_->do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08003239 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05003240 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003241
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003242 if (zip_file != nullptr) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003243 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
3244 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003245 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08003246 }
3247 }
3248
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003249 int dup_stdout_fd;
3250 int dup_stderr_fd;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003251 // Redirect stderr to log_path_ for debugging.
3252 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
3253 if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
3254 return ERROR;
3255 }
3256 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
3257 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
3258 strerror(errno));
3259 }
Nandana Dutt979388e2018-11-30 16:48:55 +00003260
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003261 // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
3262 // moved into zip file later, if zipping.
3263 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
3264 // TODO: why not write to a file instead of stdout to overcome this problem?
3265 /* TODO: rather than generating a text file now and zipping it later,
3266 it would be more efficient to redirect stdout to the zip entry
3267 directly, but the libziparchive doesn't support that option yet. */
3268 if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
3269 return ERROR;
3270 }
3271 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
3272 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
3273 tmp_path_.c_str(), strerror(errno));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003274 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08003275
3276 // Don't buffer stdout
3277 setvbuf(stdout, nullptr, _IONBF, 0);
3278
Rhed Jao5377d792020-07-16 17:37:39 +08003279 // Enable the parallel run if the client requests to output to a file.
3280 EnableParallelRunIfNeeded();
3281 // Using scope guard to make sure the dump pool can be shut down correctly.
3282 auto scope_guard_to_shutdown_pool = android::base::make_scope_guard([=]() {
3283 ShutdownDumpPool();
3284 });
3285
Felipe Leme608385d2016-02-01 10:35:38 -08003286 // NOTE: there should be no stdout output until now, otherwise it would break the header.
3287 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08003288 // duration is logged into MYLOG instead.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003289 PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003290
Kean Mariottic14cebc2024-03-04 10:55:28 +00003291 bool system_trace_exists = access(SYSTEM_TRACE_SNAPSHOT, F_OK) == 0;
3292 if (options_->use_predumped_ui_data && !system_trace_exists) {
3293 MYLOGW("Ignoring 'use predumped data' flag because no predumped data is available");
3294 options_->use_predumped_ui_data = false;
3295 }
3296
Kean Mariottica20f2d2023-12-15 09:34:25 +00003297 std::future<std::string> snapshot_system_trace;
3298
Kean Mariotti853b73a2023-07-27 12:40:30 +00003299 bool is_dumpstate_restricted =
3300 options_->telephony_only || options_->wifi_only || options_->limited_only;
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003301 if (!is_dumpstate_restricted) {
3302 // Snapshot the system trace now (if running) to avoid that dumpstate's
3303 // own activity pushes out interesting data from the trace ring buffer.
3304 // The trace file is added to the zip by MaybeAddSystemTraceToZip().
Kean Mariottica20f2d2023-12-15 09:34:25 +00003305 snapshot_system_trace = MaybeSnapshotSystemTraceAsync();
Yohei Yukawa95305b32021-03-09 07:54:27 -08003306
Kean Mariotti853b73a2023-07-27 12:40:30 +00003307 // Invoke critical dumpsys to preserve system state, before doing anything else.
3308 RunDumpsysCritical();
3309
Kean Mariotti306633e2022-09-05 16:30:47 +00003310 // Snapshot the UI traces now (if running).
3311 // The trace files will be added to bugreport later.
3312 MaybeSnapshotUiTraces();
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003313 }
Kean Mariotti853b73a2023-07-27 12:40:30 +00003314
3315 MaybeTakeEarlyScreenshot();
Kean Mariottica20f2d2023-12-15 09:34:25 +00003316 MaybeWaitForSnapshotSystemTrace(std::move(snapshot_system_trace));
Gavin Corkery6968f552020-11-22 18:09:05 +00003317 onUiIntensiveBugreportDumpsFinished(calling_uid);
3318 MaybeCheckUserConsent(calling_uid, calling_package);
3319 if (options_->telephony_only) {
3320 DumpstateTelephonyOnly(calling_package);
3321 } else if (options_->wifi_only) {
3322 DumpstateWifiOnly();
3323 } else if (options_->limited_only) {
3324 DumpstateLimitedOnly();
Elis Elliott8e401ad2023-08-08 11:18:59 +00003325 } else if (options_->onboarding_only) {
3326 DumpstateOnboardingOnly();
Gavin Corkery6968f552020-11-22 18:09:05 +00003327 } else {
Nandana Dutt4be45d12018-09-26 15:04:23 +01003328 // Dump state for the default case. This also drops root.
Jichao Lie89d9c12019-11-21 19:02:51 -08003329 RunStatus s = DumpstateDefaultAfterCritical();
Nandana Dutt5c390032019-03-12 10:52:56 +00003330 if (s != RunStatus::OK) {
Nandana Duttaac6f582019-07-26 14:32:47 +01003331 if (s == RunStatus::USER_CONSENT_DENIED) {
Nandana Dutt5c390032019-03-12 10:52:56 +00003332 HandleUserConsentDenied();
3333 }
3334 return s;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08003335 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07003336 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07003337
Felipe Leme55b42a62015-11-10 17:39:08 -08003338 /* close output if needed */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003339 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003340
Abhijeet Kaure370d682019-10-01 16:49:30 +01003341 // Zip the (now complete) .tmp file within the internal directory.
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003342 ATRACE_BEGIN("FinalizeFile");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003343 FinalizeFile();
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003344 ATRACE_END();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003345
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003346 // Share the final file with the caller if the user has consented or Shell is the caller.
Nandana Duttd2f5f082019-01-18 17:13:52 +00003347 Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
Gavin Corkerya44686c2022-11-23 18:16:51 +00003348 if (CalledByApi() && !options_->is_consent_deferred) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003349 status = CopyBugreportIfUserConsented(calling_uid);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003350 if (status != Dumpstate::RunStatus::OK &&
3351 status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3352 // Do an early return if there were errors. We make an exception for consent
3353 // timing out because it's possible the user got distracted. In this case the
3354 // bugreport is not shared but made available for manual retrieval.
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003355 MYLOGI("User denied consent. Returning\n");
Nandana Duttd2f5f082019-01-18 17:13:52 +00003356 return status;
3357 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003358 if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3359 MYLOGI(
3360 "Did not receive user consent yet."
3361 " Will not copy the bugreport artifacts to caller.\n");
Abhijeet Kaur57627412019-04-17 16:00:09 +01003362 const String16 incidentcompanion("incidentcompanion");
3363 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
3364 if (ics != nullptr) {
3365 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3366 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3367 consent_callback_.get());
3368 } else {
3369 MYLOGD("Unable to cancel user consent; incidentcompanion service unavailable\n");
3370 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003371 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003372 }
3373
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003374 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003375 if (options_->do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09003376 for (int i = 0; i < 3; i++) {
3377 Vibrate(75);
3378 usleep((75 + 50) * 1000);
3379 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003380 }
3381
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003382 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
3383 progress_->GetInitialMax());
3384 progress_->Save();
3385 MYLOGI("done (id %d)\n", id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003386
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003387 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08003388
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003389 if (control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07003390 MYLOGD("Closing control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003391 close(control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07003392 }
3393
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003394 tombstone_data_.clear();
3395 anr_data_.clear();
Andy Hungd62f7e62024-01-11 15:47:52 -08003396 anr_trace_data_.clear();
Woody Lin20767a92022-11-29 15:50:24 +08003397 shutdown_checkpoints_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01003398
Nandana Duttd2f5f082019-01-18 17:13:52 +00003399 return (consent_callback_ != nullptr &&
3400 consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
3401 ? USER_CONSENT_TIMED_OUT
3402 : RunStatus::OK;
3403}
3404
Paul Chang0d2aad72020-02-13 20:04:03 +08003405void Dumpstate::MaybeTakeEarlyScreenshot() {
3406 if (!options_->do_screenshot || !do_early_screenshot_) {
3407 return;
3408 }
3409
3410 TakeScreenshot();
3411}
3412
Kean Mariottica20f2d2023-12-15 09:34:25 +00003413std::future<std::string> Dumpstate::MaybeSnapshotSystemTraceAsync() {
Kean Mariotti853b73a2023-07-27 12:40:30 +00003414 // When capturing traces via bugreport handler (BH), this function will be invoked twice:
3415 // 1) When BH invokes IDumpstate::PreDumpUiData()
3416 // 2) When BH invokes IDumpstate::startBugreport(flags = BUGREPORT_USE_PREDUMPED_UI_DATA)
3417 // In this case we don't want to re-invoke perfetto in step 2.
3418 // In all other standard invocation states, this function is invoked once
3419 // without the flag BUGREPORT_USE_PREDUMPED_UI_DATA.
Kean Mariottica20f2d2023-12-15 09:34:25 +00003420 // This function must run asynchronously to avoid delaying MaybeTakeEarlyScreenshot() in the
3421 // standard invocation states (b/316110955).
Kean Mariotti853b73a2023-07-27 12:40:30 +00003422 if (options_->use_predumped_ui_data) {
Kean Mariottica20f2d2023-12-15 09:34:25 +00003423 return {};
3424 }
3425
3426 // Create temporary file for the command's output
3427 std::string outPath = ds.bugreport_internal_dir_ + "/tmp_serialize_perfetto_trace";
3428 auto outFd = android::base::unique_fd(TEMP_FAILURE_RETRY(
3429 open(outPath.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
3430 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
3431 if (outFd < 0) {
3432 MYLOGE("Could not open %s to serialize perfetto trace.\n", outPath.c_str());
3433 return {};
Kean Mariotti853b73a2023-07-27 12:40:30 +00003434 }
3435
3436 // If a stale file exists already, remove it.
3437 unlink(SYSTEM_TRACE_SNAPSHOT);
3438
Kean Mariottica20f2d2023-12-15 09:34:25 +00003439 MYLOGI("Launching async '%s'", SERIALIZE_PERFETTO_TRACE_TASK.c_str())
3440 return std::async(
3441 std::launch::async, [this, outPath = std::move(outPath), outFd = std::move(outFd)] {
3442 // If a background system trace is happening and is marked as "suitable for
3443 // bugreport" (i.e. bugreport_score > 0 in the trace config), this command
3444 // will stop it and serialize into SYSTEM_TRACE_SNAPSHOT. In the (likely)
3445 // case that no trace is ongoing, this command is a no-op.
3446 // Note: this should not be enqueued as we need to freeze the trace before
3447 // dumpstate starts. Otherwise the trace ring buffers will contain mostly
3448 // the dumpstate's own activity which is irrelevant.
3449 RunCommand(
3450 SERIALIZE_PERFETTO_TRACE_TASK, {"perfetto", "--save-for-bugreport"},
3451 CommandOptions::WithTimeout(10).DropRoot().CloseAllFileDescriptorsOnExec().Build(),
3452 false, outFd);
3453 // MaybeAddSystemTraceToZip() will take care of copying the trace in the zip
3454 // file in the later stages.
3455
3456 return outPath;
3457 });
3458}
3459
3460void Dumpstate::MaybeWaitForSnapshotSystemTrace(std::future<std::string> task) {
3461 if (!task.valid()) {
3462 return;
3463 }
3464
3465 WaitForTask(std::move(task), SERIALIZE_PERFETTO_TRACE_TASK, STDOUT_FILENO);
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003466}
3467
Kean Mariotti306633e2022-09-05 16:30:47 +00003468void Dumpstate::MaybeSnapshotUiTraces() {
3469 if (PropertiesHelper::IsUserBuild() || options_->use_predumped_ui_data) {
3470 return;
3471 }
3472
Pablo Gamito654831c2024-02-16 16:47:48 +00003473 std::vector<std::vector<std::string>> dumpTracesForBugReportCommands = {
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003474 {"cmd", "input_method", "tracing", "save-for-bugreport"},
3475 {"cmd", "window", "tracing", "save-for-bugreport"},
3476 {"cmd", "window", "shell", "tracing", "save-for-bugreport"},
3477 };
Hongwei Wang39229132023-01-24 15:09:59 -08003478
Pablo Gamito654831c2024-02-16 16:47:48 +00003479 if (!android_tracing_perfetto_transition_tracing()) {
3480 dumpTracesForBugReportCommands.push_back({"dumpsys", "activity", "service",
3481 "SystemUIService", "WMShell", "transitions",
3482 "tracing", "save-for-bugreport"});
3483 }
3484
Pablo Gamito6929a0e2024-02-26 23:29:47 +00003485 if (!android_tracing_perfetto_protolog_tracing()) {
Pablo Gamito654831c2024-02-16 16:47:48 +00003486 dumpTracesForBugReportCommands.push_back({"dumpsys", "activity", "service",
3487 "SystemUIService", "WMShell", "protolog",
3488 "save-for-bugreport"});
3489 }
3490
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003491 for (const auto& command : dumpTracesForBugReportCommands) {
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003492 RunCommand(
3493 // Empty name because it's not intended to be classified as a bugreport section.
3494 // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003495 "", command,
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003496 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
3497 }
Kean Mariotti306633e2022-09-05 16:30:47 +00003498}
3499
3500void Dumpstate::MaybeAddUiTracesToZip() {
3501 if (PropertiesHelper::IsUserBuild()) {
3502 return;
3503 }
3504
3505 ds.AddDir(WMTRACE_DATA_DIR, false);
Yohei Yukawa95305b32021-03-09 07:54:27 -08003506}
3507
Paul Changeb4b4642020-05-28 22:05:47 +08003508void Dumpstate::onUiIntensiveBugreportDumpsFinished(int32_t calling_uid) {
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003509 if (multiuser_get_app_id(calling_uid) == AID_SHELL || !CalledByApi()) {
Paul Changc490e662020-04-11 18:14:09 +08003510 return;
3511 }
3512 if (listener_ != nullptr) {
3513 // Let listener know ui intensive bugreport dumps are finished, then it can do event
3514 // handling if required.
Paul Changeb4b4642020-05-28 22:05:47 +08003515 listener_->onUiIntensiveBugreportDumpsFinished();
Paul Changc490e662020-04-11 18:14:09 +08003516 }
3517}
3518
Jichao Lie89d9c12019-11-21 19:02:51 -08003519void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) {
Gavin Corkerya44686c2022-11-23 18:16:51 +00003520 if (multiuser_get_app_id(calling_uid) == AID_SHELL ||
Kholoud Mohameddef4e432024-05-15 12:47:46 +00003521 !CalledByApi() || options_->is_consent_deferred ||
3522 (android::app::admin::flags::onboarding_consentless_bugreports() &&
3523 options_->skip_user_consent)) {
Gavin Corkerya44686c2022-11-23 18:16:51 +00003524 // No need to get consent for shell triggered dumpstates, or not
3525 // through bugreporting API (i.e. no fd to copy back), or when consent
3526 // is deferred.
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003527 return;
3528 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003529 consent_callback_ = new ConsentCallback();
3530 const String16 incidentcompanion("incidentcompanion");
3531 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
Jichao Lie89d9c12019-11-21 19:02:51 -08003532 android::String16 package(calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003533 if (ics != nullptr) {
3534 MYLOGD("Checking user consent via incidentcompanion service\n");
Steven Leeb573eb82022-11-29 22:31:35 +08003535 int flags = 0x1; // IncidentManager.FLAG_CONFIRMATION_DIALOG
3536 if (IsConsentlessBugreportAllowed(*options_)) {
3537 flags |= 0x2; // IncidentManager.FLAG_ALLOW_CONSENTLESS_BUGREPORT
3538 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003539 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
Steven Leeb573eb82022-11-29 22:31:35 +08003540 calling_uid, package, String16(), String16(), flags, consent_callback_.get());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003541 } else {
3542 MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
3543 }
3544}
3545
Nandana Dutt5c390032019-03-12 10:52:56 +00003546bool Dumpstate::IsUserConsentDenied() const {
3547 return ds.consent_callback_ != nullptr &&
3548 ds.consent_callback_->getResult() == UserConsentResult::DENIED;
3549}
3550
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01003551bool Dumpstate::CalledByApi() const {
3552 return ds.options_->bugreport_fd.get() != -1 ? true : false;
3553}
3554
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003555void Dumpstate::CleanupTmpFiles() {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003556 android::os::UnlinkAndLogOnError(tmp_path_);
3557 android::os::UnlinkAndLogOnError(screenshot_path_);
3558 android::os::UnlinkAndLogOnError(path_);
Gavin Corkery789d7a52021-02-24 23:52:35 +00003559 if (dump_traces_path != nullptr) {
3560 android::os::UnlinkAndLogOnError(dump_traces_path);
3561 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003562}
3563
Rhed Jao5377d792020-07-16 17:37:39 +08003564void Dumpstate::EnableParallelRunIfNeeded() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003565 if (!PropertiesHelper::IsParallelRun()) {
Rhed Jao5377d792020-07-16 17:37:39 +08003566 return;
3567 }
3568 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003569 zip_entry_tasks_ = std::make_unique<TaskQueue>();
Rhed Jao5377d792020-07-16 17:37:39 +08003570}
3571
3572void Dumpstate::ShutdownDumpPool() {
3573 if (dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08003574 dump_pool_.reset();
Rhed Jao5377d792020-07-16 17:37:39 +08003575 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003576 if (zip_entry_tasks_) {
3577 zip_entry_tasks_->run(/* do_cancel = */true);
3578 zip_entry_tasks_ = nullptr;
3579 }
3580}
3581
3582void Dumpstate::EnqueueAddZipEntryAndCleanupIfNeeded(const std::string& entry_name,
3583 const std::string& entry_path) {
3584 auto func_add_zip_entry_and_cleanup = [=](bool task_cancelled) {
3585 if (!task_cancelled) {
3586 AddZipEntry(entry_name, entry_path);
3587 }
3588 android::os::UnlinkAndLogOnError(entry_path);
3589 };
3590 if (zip_entry_tasks_) {
3591 // Enqueues AddZipEntryAndCleanup function if the parallel run is enabled.
3592 zip_entry_tasks_->add(func_add_zip_entry_and_cleanup, _1);
3593 } else {
3594 // Invokes AddZipEntryAndCleanup immediately
3595 std::invoke(func_add_zip_entry_and_cleanup, /* task_cancelled = */false);
3596 }
Rhed Jao5377d792020-07-16 17:37:39 +08003597}
3598
Nandana Duttd2f5f082019-01-18 17:13:52 +00003599Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
3600 MYLOGD("User denied consent; deleting files and returning\n");
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003601 CleanupTmpFiles();
Nandana Duttd2f5f082019-01-18 17:13:52 +00003602 return USER_CONSENT_DENIED;
3603}
3604
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003605Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented(int32_t calling_uid) {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003606 // If the caller has asked to copy the bugreport over to their directory, we need explicit
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003607 // user consent (unless the caller is Shell).
3608 UserConsentResult consent_result;
Kholoud Mohameddef4e432024-05-15 12:47:46 +00003609 if (multiuser_get_app_id(calling_uid) == AID_SHELL || (options_->skip_user_consent
3610 && android::app::admin::flags::onboarding_consentless_bugreports())) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003611 consent_result = UserConsentResult::APPROVED;
3612 } else {
3613 consent_result = consent_callback_->getResult();
3614 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003615 if (consent_result == UserConsentResult::UNAVAILABLE) {
3616 // User has not responded yet.
3617 uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
Hunter Knepshield70610fa2020-01-03 15:27:33 -08003618 // Telephony is a fast report type, particularly on user builds where information may be
3619 // more aggressively limited. To give the user time to read the consent dialog, increase the
3620 // timeout.
3621 uint64_t timeout_ms = options_->telephony_only ? TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS
3622 : USER_CONSENT_TIMEOUT_MS;
3623 if (elapsed_ms < timeout_ms) {
3624 uint delay_seconds = (timeout_ms - elapsed_ms) / 1000;
Nandana Duttd2f5f082019-01-18 17:13:52 +00003625 MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
3626 sleep(delay_seconds);
3627 }
3628 consent_result = consent_callback_->getResult();
3629 }
3630 if (consent_result == UserConsentResult::DENIED) {
3631 // User has explicitly denied sharing with the app. To be safe delete the
3632 // internal bugreport & tmp files.
3633 return HandleUserConsentDenied();
3634 }
3635 if (consent_result == UserConsentResult::APPROVED) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00003636 bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
3637 if (copy_succeeded) {
3638 android::os::UnlinkAndLogOnError(path_);
Abhijeet Kaur9ce94672020-04-01 17:22:36 +01003639 if (options_->do_screenshot &&
3640 options_->screenshot_fd.get() != -1 &&
3641 !options_->is_screenshot_copied) {
3642 copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
3643 options_->screenshot_fd.get());
3644 options_->is_screenshot_copied = copy_succeeded;
3645 if (copy_succeeded) {
3646 android::os::UnlinkAndLogOnError(screenshot_path_);
3647 }
3648 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003649 }
3650 return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
3651 } else if (consent_result == UserConsentResult::UNAVAILABLE) {
3652 // consent_result is still UNAVAILABLE. The user has likely not responded yet.
3653 // Since we do not have user consent to share the bugreport it does not get
3654 // copied over to the calling app but remains in the internal directory from
3655 // where the user can manually pull it.
Paul Changce644212021-05-11 16:06:45 +08003656 std::string final_path = GetPath(".zip");
3657 bool copy_succeeded = android::os::CopyFileToFile(path_, final_path);
3658 if (copy_succeeded) {
3659 android::os::UnlinkAndLogOnError(path_);
3660 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003661 return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
3662 }
3663 // Unknown result; must be a programming error.
3664 MYLOGE("Unknown user consent result:%d\n", consent_result);
3665 return Dumpstate::RunStatus::ERROR;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003666}
3667
Nandana Duttf02564e2019-02-15 15:24:24 +00003668Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003669 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
3670 Dumpstate::RunStatus status = options->Initialize(argc, argv);
3671 if (status == Dumpstate::RunStatus::OK) {
Nandana Duttf02564e2019-02-15 15:24:24 +00003672 SetOptions(std::move(options));
Nandana Duttd2f5f082019-01-18 17:13:52 +00003673 // When directly running dumpstate binary, the output is not expected to be written
3674 // to any external file descriptor.
Nandana Duttf02564e2019-02-15 15:24:24 +00003675 assert(options_->bugreport_fd.get() == -1);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003676
3677 // calling_uid and calling_package are for user consent to share the bugreport with
Abhijeet Kaura407fb82020-03-27 12:51:12 +00003678 // an app; they are irrelevant here because bugreport is triggered via command line.
3679 // Update Last ID before calling Run().
3680 Initialize();
Nikhil Kumarb70622a2023-06-15 15:37:19 +01003681 status = Run(0 /* calling_uid */, "" /* calling_package */);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003682 }
Nandana Duttf02564e2019-02-15 15:24:24 +00003683 return status;
3684}
3685
3686/* Main entry point for dumpstate binary. */
3687int run_main(int argc, char* argv[]) {
3688 Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003689
3690 switch (status) {
3691 case Dumpstate::RunStatus::OK:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003692 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003693 case Dumpstate::RunStatus::HELP:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003694 ShowUsage();
3695 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003696 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003697 fprintf(stderr, "Invalid combination of args\n");
3698 ShowUsage();
3699 exit(1);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003700 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003701 FALLTHROUGH_INTENDED;
3702 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3703 FALLTHROUGH_INTENDED;
3704 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003705 exit(2);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003706 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003707}
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003708
3709// TODO(111441001): Default DumpOptions to sensible values.
3710Dumpstate::Dumpstate(const std::string& version)
3711 : pid_(getpid()),
3712 options_(new Dumpstate::DumpOptions()),
Nandana Dutt402a8392019-06-14 14:25:13 +01003713 last_reported_percent_progress_(0),
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003714 version_(version),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003715 now_(time(nullptr)),
3716 open_socket_fn_(open_socket) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003717}
3718
3719Dumpstate& Dumpstate::GetInstance() {
3720 static Dumpstate singleton_(android::base::GetProperty("dumpstate.version", VERSION_CURRENT));
3721 return singleton_;
3722}
3723
Rhed Jao5377d792020-07-16 17:37:39 +08003724DurationReporter::DurationReporter(const std::string& title, bool logcat_only, bool verbose,
3725 int duration_fd) : title_(title), logcat_only_(logcat_only), verbose_(verbose),
3726 duration_fd_(duration_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003727 if (!title_.empty()) {
3728 started_ = Nanotime();
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003729 if (title_.find("SHOW MAP") == std::string::npos) {
3730 ATRACE_ASYNC_BEGIN(title_.c_str(), 0);
3731 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003732 }
3733}
3734
3735DurationReporter::~DurationReporter() {
3736 if (!title_.empty()) {
3737 float elapsed = (float)(Nanotime() - started_) / NANOS_PER_SEC;
chenqiwuaf8b2d92019-12-12 18:53:51 +08003738 if (elapsed >= .5f || verbose_) {
3739 MYLOGD("Duration of '%s': %.2fs\n", title_.c_str(), elapsed);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003740 }
chenqiwuaf8b2d92019-12-12 18:53:51 +08003741 if (!logcat_only_) {
3742 // Use "Yoda grammar" to make it easier to grep|sort sections.
Rhed Jao5377d792020-07-16 17:37:39 +08003743 dprintf(duration_fd_, "------ %.3fs was the duration of '%s' ------\n",
3744 elapsed, title_.c_str());
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003745 }
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003746 if (title_.find("SHOW MAP") == std::string::npos) {
3747 ATRACE_ASYNC_END(title_.c_str(), 0);
3748 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003749 }
3750}
3751
3752const int32_t Progress::kDefaultMax = 5000;
3753
3754Progress::Progress(const std::string& path) : Progress(Progress::kDefaultMax, 1.1, path) {
3755}
3756
3757Progress::Progress(int32_t initial_max, int32_t progress, float growth_factor)
3758 : Progress(initial_max, growth_factor, "") {
3759 progress_ = progress;
3760}
3761
3762Progress::Progress(int32_t initial_max, float growth_factor, const std::string& path)
3763 : initial_max_(initial_max),
3764 progress_(0),
3765 max_(initial_max),
3766 growth_factor_(growth_factor),
3767 n_runs_(0),
3768 average_max_(0),
3769 path_(path) {
3770 if (!path_.empty()) {
3771 Load();
3772 }
3773}
3774
3775void Progress::Load() {
3776 MYLOGD("Loading stats from %s\n", path_.c_str());
3777 std::string content;
3778 if (!android::base::ReadFileToString(path_, &content)) {
3779 MYLOGI("Could not read stats from %s; using max of %d\n", path_.c_str(), max_);
3780 return;
3781 }
3782 if (content.empty()) {
3783 MYLOGE("No stats (empty file) on %s; using max of %d\n", path_.c_str(), max_);
3784 return;
3785 }
3786 std::vector<std::string> lines = android::base::Split(content, "\n");
3787
3788 if (lines.size() < 1) {
3789 MYLOGE("Invalid stats on file %s: not enough lines (%d). Using max of %d\n", path_.c_str(),
3790 (int)lines.size(), max_);
3791 return;
3792 }
3793 char* ptr;
3794 n_runs_ = strtol(lines[0].c_str(), &ptr, 10);
3795 average_max_ = strtol(ptr, nullptr, 10);
3796 if (n_runs_ <= 0 || average_max_ <= 0 || n_runs_ > STATS_MAX_N_RUNS ||
3797 average_max_ > STATS_MAX_AVERAGE) {
3798 MYLOGE("Invalid stats line on file %s: %s\n", path_.c_str(), lines[0].c_str());
3799 initial_max_ = Progress::kDefaultMax;
3800 } else {
3801 initial_max_ = average_max_;
3802 }
3803 max_ = initial_max_;
3804
3805 MYLOGI("Average max progress: %d in %d runs; estimated max: %d\n", average_max_, n_runs_, max_);
3806}
3807
3808void Progress::Save() {
3809 int32_t total = n_runs_ * average_max_ + progress_;
3810 int32_t runs = n_runs_ + 1;
3811 int32_t average = floor(((float)total) / runs);
3812 MYLOGI("Saving stats (total=%d, runs=%d, average=%d) on %s\n", total, runs, average,
3813 path_.c_str());
3814 if (path_.empty()) {
3815 return;
3816 }
3817
3818 std::string content = android::base::StringPrintf("%d %d\n", runs, average);
3819 if (!android::base::WriteStringToFile(content, path_)) {
3820 MYLOGE("Could not save stats on %s\n", path_.c_str());
3821 }
3822}
3823
3824int32_t Progress::Get() const {
3825 return progress_;
3826}
3827
3828bool Progress::Inc(int32_t delta_sec) {
3829 bool changed = false;
3830 if (delta_sec >= 0) {
3831 progress_ += delta_sec;
3832 if (progress_ > max_) {
3833 int32_t old_max = max_;
3834 max_ = floor((float)progress_ * growth_factor_);
3835 MYLOGD("Adjusting max progress from %d to %d\n", old_max, max_);
3836 changed = true;
3837 }
3838 }
3839 return changed;
3840}
3841
3842int32_t Progress::GetMax() const {
3843 return max_;
3844}
3845
3846int32_t Progress::GetInitialMax() const {
3847 return initial_max_;
3848}
3849
3850void Progress::Dump(int fd, const std::string& prefix) const {
3851 const char* pr = prefix.c_str();
3852 dprintf(fd, "%sprogress: %d\n", pr, progress_);
3853 dprintf(fd, "%smax: %d\n", pr, max_);
3854 dprintf(fd, "%sinitial_max: %d\n", pr, initial_max_);
3855 dprintf(fd, "%sgrowth_factor: %0.2f\n", pr, growth_factor_);
3856 dprintf(fd, "%spath: %s\n", pr, path_.c_str());
3857 dprintf(fd, "%sn_runs: %d\n", pr, n_runs_);
3858 dprintf(fd, "%saverage_max: %d\n", pr, average_max_);
3859}
3860
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003861std::string Dumpstate::GetPath(const std::string& suffix) const {
3862 return GetPath(bugreport_internal_dir_, suffix);
3863}
3864
3865std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
3866 return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
3867 name_.c_str(), suffix.c_str());
3868}
3869
3870void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
3871 progress_ = std::move(progress);
3872}
3873
3874void for_each_userid(void (*func)(int), const char *header) {
3875 std::string title = header == nullptr ? "for_each_userid" : android::base::StringPrintf(
3876 "for_each_userid(%s)", header);
3877 DurationReporter duration_reporter(title);
3878 if (PropertiesHelper::IsDryRun()) return;
3879
3880 DIR *d;
3881 struct dirent *de;
3882
3883 if (header) printf("\n------ %s ------\n", header);
3884 func(0);
3885
3886 if (!(d = opendir("/data/system/users"))) {
3887 printf("Failed to open /data/system/users (%s)\n", strerror(errno));
3888 return;
3889 }
3890
3891 while ((de = readdir(d))) {
3892 int userid;
3893 if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
3894 continue;
3895 }
3896 func(userid);
3897 }
3898
3899 closedir(d);
3900}
3901
3902static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
3903 DIR *d;
3904 struct dirent *de;
3905
3906 if (!(d = opendir("/proc"))) {
3907 printf("Failed to open /proc (%s)\n", strerror(errno));
3908 return;
3909 }
3910
3911 if (header) printf("\n------ %s ------\n", header);
3912 while ((de = readdir(d))) {
3913 if (ds.IsUserConsentDenied()) {
3914 MYLOGE(
3915 "Returning early because user denied consent to share bugreport with calling app.");
3916 closedir(d);
3917 return;
3918 }
3919 int pid;
3920 int fd;
3921 char cmdpath[255];
3922 char cmdline[255];
3923
3924 if (!(pid = atoi(de->d_name))) {
3925 continue;
3926 }
3927
3928 memset(cmdline, 0, sizeof(cmdline));
3929
3930 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
3931 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3932 TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
3933 close(fd);
3934 if (cmdline[0]) {
3935 helper(pid, cmdline, arg);
3936 continue;
3937 }
3938 }
3939
3940 // if no cmdline, a kernel thread has comm
3941 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
3942 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3943 TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
3944 close(fd);
3945 if (cmdline[1]) {
3946 cmdline[0] = '[';
3947 size_t len = strcspn(cmdline, "\f\b\r\n");
3948 cmdline[len] = ']';
3949 cmdline[len+1] = '\0';
3950 }
3951 }
3952 if (!cmdline[0]) {
3953 strcpy(cmdline, "N/A");
3954 }
3955 helper(pid, cmdline, arg);
3956 }
3957
3958 closedir(d);
3959}
3960
3961static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
3962 for_each_pid_func *func = (for_each_pid_func*) arg;
3963 func(pid, cmdline);
3964}
3965
3966void for_each_pid(for_each_pid_func func, const char *header) {
3967 std::string title = header == nullptr ? "for_each_pid"
3968 : android::base::StringPrintf("for_each_pid(%s)", header);
3969 DurationReporter duration_reporter(title);
3970 if (PropertiesHelper::IsDryRun()) return;
3971
3972 __for_each_pid(for_each_pid_helper, header, (void *) func);
3973}
3974
3975static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
3976 DIR *d;
3977 struct dirent *de;
3978 char taskpath[255];
3979 for_each_tid_func *func = (for_each_tid_func *) arg;
3980
3981 snprintf(taskpath, sizeof(taskpath), "/proc/%d/task", pid);
3982
3983 if (!(d = opendir(taskpath))) {
3984 printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
3985 return;
3986 }
3987
3988 func(pid, pid, cmdline);
3989
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 tid;
3998 int fd;
3999 char commpath[255];
4000 char comm[255];
4001
4002 if (!(tid = atoi(de->d_name))) {
4003 continue;
4004 }
4005
4006 if (tid == pid)
4007 continue;
4008
4009 snprintf(commpath, sizeof(commpath), "/proc/%d/comm", tid);
4010 memset(comm, 0, sizeof(comm));
4011 if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
4012 strcpy(comm, "N/A");
4013 } else {
4014 char *c;
4015 TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
4016 close(fd);
4017
4018 c = strrchr(comm, '\n');
4019 if (c) {
4020 *c = '\0';
4021 }
4022 }
4023 func(pid, tid, comm);
4024 }
4025
4026 closedir(d);
4027}
4028
4029void for_each_tid(for_each_tid_func func, const char *header) {
4030 std::string title = header == nullptr ? "for_each_tid"
4031 : android::base::StringPrintf("for_each_tid(%s)", header);
4032 DurationReporter duration_reporter(title);
4033
4034 if (PropertiesHelper::IsDryRun()) return;
4035
4036 __for_each_pid(for_each_tid_helper, header, (void *) func);
4037}
4038
4039void show_wchan(int pid, int tid, const char *name) {
4040 if (PropertiesHelper::IsDryRun()) return;
4041
4042 char path[255];
4043 char buffer[255];
4044 int fd, ret, save_errno;
4045 char name_buffer[255];
4046
4047 memset(buffer, 0, sizeof(buffer));
4048
4049 snprintf(path, sizeof(path), "/proc/%d/wchan", tid);
4050 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
4051 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
4052 return;
4053 }
4054
4055 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
4056 save_errno = errno;
4057 close(fd);
4058
4059 if (ret < 0) {
4060 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
4061 return;
4062 }
4063
4064 snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
4065 pid == tid ? 0 : 3, "", name);
4066
4067 printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
4068
4069 return;
4070}
4071
4072// print time in centiseconds
4073static void snprcent(char *buffer, size_t len, size_t spc,
4074 unsigned long long time) {
4075 static long hz; // cache discovered hz
4076
4077 if (hz <= 0) {
4078 hz = sysconf(_SC_CLK_TCK);
4079 if (hz <= 0) {
4080 hz = 1000;
4081 }
4082 }
4083
4084 // convert to centiseconds
4085 time = (time * 100 + (hz / 2)) / hz;
4086
4087 char str[16];
4088
4089 snprintf(str, sizeof(str), " %llu.%02u",
4090 time / 100, (unsigned)(time % 100));
4091 size_t offset = strlen(buffer);
4092 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
4093 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
4094}
4095
4096// print permille as a percent
4097static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
4098 char str[16];
4099
4100 snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
4101 size_t offset = strlen(buffer);
4102 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
4103 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
4104}
4105
4106void show_showtime(int pid, const char *name) {
4107 if (PropertiesHelper::IsDryRun()) return;
4108
4109 char path[255];
4110 char buffer[1023];
4111 int fd, ret, save_errno;
4112
4113 memset(buffer, 0, sizeof(buffer));
4114
4115 snprintf(path, sizeof(path), "/proc/%d/stat", pid);
4116 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
4117 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
4118 return;
4119 }
4120
4121 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
4122 save_errno = errno;
4123 close(fd);
4124
4125 if (ret < 0) {
4126 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
4127 return;
4128 }
4129
4130 // field 14 is utime
4131 // field 15 is stime
4132 // field 42 is iotime
4133 unsigned long long utime = 0, stime = 0, iotime = 0;
4134 if (sscanf(buffer,
4135 "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
4136 "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
4137 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
4138 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
4139 &utime, &stime, &iotime) != 3) {
4140 return;
4141 }
4142
4143 unsigned long long total = utime + stime;
4144 if (!total) {
4145 return;
4146 }
4147
4148 unsigned permille = (iotime * 1000 + (total / 2)) / total;
4149 if (permille > 1000) {
4150 permille = 1000;
4151 }
4152
4153 // try to beautify and stabilize columns at <80 characters
4154 snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
4155 if ((name[0] != '[') || utime) {
4156 snprcent(buffer, sizeof(buffer), 57, utime);
4157 }
4158 snprcent(buffer, sizeof(buffer), 65, stime);
4159 if ((name[0] != '[') || iotime) {
4160 snprcent(buffer, sizeof(buffer), 73, iotime);
4161 }
4162 if (iotime) {
4163 snprdec(buffer, sizeof(buffer), 79, permille);
4164 }
4165 puts(buffer); // adds a trailing newline
4166
4167 return;
4168}
4169
4170void do_dmesg() {
4171 const char *title = "KERNEL LOG (dmesg)";
4172 DurationReporter duration_reporter(title);
4173 printf("------ %s ------\n", title);
4174
4175 if (PropertiesHelper::IsDryRun()) return;
4176
4177 /* Get size of kernel buffer */
4178 int size = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
4179 if (size <= 0) {
4180 printf("Unexpected klogctl return value: %d\n\n", size);
4181 return;
4182 }
4183 char *buf = (char *) malloc(size + 1);
4184 if (buf == nullptr) {
4185 printf("memory allocation failed\n\n");
4186 return;
4187 }
4188 int retval = klogctl(KLOG_READ_ALL, buf, size);
4189 if (retval < 0) {
4190 printf("klogctl failure\n\n");
4191 free(buf);
4192 return;
4193 }
4194 buf[retval] = '\0';
4195 printf("%s\n\n", buf);
4196 free(buf);
4197 return;
4198}
4199
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004200int Dumpstate::DumpFile(const std::string& title, const std::string& path) {
4201 DurationReporter duration_reporter(title);
4202
4203 int status = DumpFileToFd(STDOUT_FILENO, title, path);
4204
4205 UpdateProgress(WEIGHT_FILE);
4206
4207 return status;
4208}
4209
4210int read_file_as_long(const char *path, long int *output) {
luoqiangwei15fcf2022024-03-07 15:29:20 +08004211 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
4212 if (fd.get() < 0) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004213 int err = errno;
4214 MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
4215 return -1;
4216 }
4217 char buffer[50];
luoqiangwei15fcf2022024-03-07 15:29:20 +08004218 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer, sizeof(buffer)));
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004219 if (bytes_read == -1) {
4220 MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
4221 return -2;
4222 }
4223 if (bytes_read == 0) {
4224 MYLOGE("File %s is empty\n", path);
4225 return -3;
4226 }
4227 *output = atoi(buffer);
4228 return 0;
4229}
4230
4231/* calls skip to gate calling dump_from_fd recursively
4232 * in the specified directory. dump_from_fd defaults to
4233 * dump_file_from_fd above when set to NULL. skip defaults
4234 * to false when set to NULL. dump_from_fd will always be
4235 * called with title NULL.
4236 */
4237int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
4238 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4239 DurationReporter duration_reporter(title);
4240 DIR *dirp;
4241 struct dirent *d;
4242 char *newpath = nullptr;
4243 const char *slash = "/";
4244 int retval = 0;
4245
4246 if (!title.empty()) {
4247 printf("------ %s (%s) ------\n", title.c_str(), dir);
4248 }
4249 if (PropertiesHelper::IsDryRun()) return 0;
4250
4251 if (dir[strlen(dir) - 1] == '/') {
4252 ++slash;
4253 }
4254 dirp = opendir(dir);
4255 if (dirp == nullptr) {
4256 retval = -errno;
4257 MYLOGE("%s: %s\n", dir, strerror(errno));
4258 return retval;
4259 }
4260
4261 if (!dump_from_fd) {
4262 dump_from_fd = dump_file_from_fd;
4263 }
4264 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4265 if ((d->d_name[0] == '.')
4266 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4267 || (d->d_name[1] == '\0'))) {
4268 continue;
4269 }
4270 asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
4271 (d->d_type == DT_DIR) ? "/" : "");
4272 if (!newpath) {
4273 retval = -errno;
4274 continue;
4275 }
4276 if (skip && (*skip)(newpath)) {
4277 continue;
4278 }
4279 if (d->d_type == DT_DIR) {
4280 int ret = dump_files("", newpath, skip, dump_from_fd);
4281 if (ret < 0) {
4282 retval = ret;
4283 }
4284 continue;
4285 }
4286 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
4287 if (fd.get() < 0) {
4288 retval = -1;
4289 printf("*** %s: %s\n", newpath, strerror(errno));
4290 continue;
4291 }
4292 (*dump_from_fd)(nullptr, newpath, fd.get());
4293 }
4294 closedir(dirp);
4295 if (!title.empty()) {
4296 printf("\n");
4297 }
4298 return retval;
4299}
4300
4301/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
4302 * it's possible to avoid issues where opening the file itself can get
4303 * stuck.
4304 */
4305int dump_file_from_fd(const char *title, const char *path, int fd) {
4306 if (PropertiesHelper::IsDryRun()) return 0;
4307
4308 int flags = fcntl(fd, F_GETFL);
4309 if (flags == -1) {
4310 printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
4311 return -1;
4312 } else if (!(flags & O_NONBLOCK)) {
4313 printf("*** %s: fd must have O_NONBLOCK set.\n", path);
4314 return -1;
4315 }
4316 return DumpFileFromFdToFd(title, path, fd, STDOUT_FILENO, PropertiesHelper::IsDryRun());
4317}
4318
4319int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004320 const CommandOptions& options, bool verbose_duration, int out_fd) {
4321 DurationReporter duration_reporter(title, false /* logcat_only */,
4322 verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004323
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004324 int status = RunCommandToFd(out_fd, title, full_command, options);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004325
4326 /* TODO: for now we're simplifying the progress calculation by using the
4327 * timeout as the weight. It's a good approximation for most cases, except when calling dumpsys,
4328 * where its weight should be much higher proportionally to its timeout.
4329 * Ideally, it should use a options.EstimatedDuration() instead...*/
4330 UpdateProgress(options.Timeout());
4331
4332 return status;
4333}
4334
4335void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
Rhed Jaoe017f982020-07-21 17:58:41 +08004336 const CommandOptions& options, long dumpsysTimeoutMs, int out_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004337 long timeout_ms = dumpsysTimeoutMs > 0 ? dumpsysTimeoutMs : options.TimeoutInMs();
4338 std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-T", std::to_string(timeout_ms)};
4339 dumpsys.insert(dumpsys.end(), dumpsys_args.begin(), dumpsys_args.end());
Rhed Jaoe017f982020-07-21 17:58:41 +08004340 RunCommand(title, dumpsys, options, false, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004341}
4342
Dieter Hsu105ad0c2020-09-29 15:23:33 +08004343static int open_socket(const char* service) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004344 int s = android_get_control_socket(service);
4345 if (s < 0) {
4346 MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
4347 return -1;
4348 }
4349 fcntl(s, F_SETFD, FD_CLOEXEC);
4350
4351 // Set backlog to 0 to make sure that queue size will be minimum.
4352 // In Linux, because the minimum queue will be 1, connect() will be blocked
4353 // if the other clients already called connect() and the connection request was not accepted.
4354 if (listen(s, 0) < 0) {
4355 MYLOGE("listen(control socket): %s\n", strerror(errno));
4356 return -1;
4357 }
4358
4359 struct sockaddr addr;
4360 socklen_t alen = sizeof(addr);
Abhijeet Kaur2113cae2019-09-13 09:24:15 +01004361 int fd = accept4(s, &addr, &alen, SOCK_CLOEXEC);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004362
4363 // Close socket just after accept(), to make sure that connect() by client will get error
4364 // when the socket is used by the other services.
4365 // There is still a race condition possibility between accept and close, but there is no way
4366 // to close-on-accept atomically.
4367 // See detail; b/123306389#comment25
4368 close(s);
4369
4370 if (fd < 0) {
4371 MYLOGE("accept(control socket): %s\n", strerror(errno));
4372 return -1;
4373 }
4374
4375 return fd;
4376}
4377
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004378// TODO: should call is_valid_output_file and/or be merged into it.
4379void create_parent_dirs(const char *path) {
4380 char *chp = const_cast<char *> (path);
4381
4382 /* skip initial slash */
4383 if (chp[0] == '/')
4384 chp++;
4385
4386 /* create leading directories, if necessary */
4387 struct stat dir_stat;
4388 while (chp && chp[0]) {
4389 chp = strchr(chp, '/');
4390 if (chp) {
4391 *chp = 0;
4392 if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
4393 MYLOGI("Creating directory %s\n", path);
4394 if (mkdir(path, 0770)) { /* drwxrwx--- */
4395 MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
4396 } else if (chown(path, AID_SHELL, AID_SHELL)) {
4397 MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
4398 }
4399 }
4400 *chp++ = '/';
4401 }
4402 }
4403}
4404
4405bool _redirect_to_file(FILE* redirect, char* path, int truncate_flag) {
4406 create_parent_dirs(path);
4407
4408 int fd = TEMP_FAILURE_RETRY(open(path,
4409 O_WRONLY | O_CREAT | truncate_flag | O_CLOEXEC | O_NOFOLLOW,
4410 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
4411 if (fd < 0) {
4412 MYLOGE("%s: %s\n", path, strerror(errno));
4413 return false;
4414 }
4415
4416 TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
4417 close(fd);
4418 return true;
4419}
4420
4421bool redirect_to_file(FILE* redirect, char* path) {
4422 return _redirect_to_file(redirect, path, O_TRUNC);
4423}
4424
4425bool redirect_to_existing_file(FILE* redirect, char* path) {
4426 return _redirect_to_file(redirect, path, O_APPEND);
4427}
4428
4429void dump_route_tables() {
4430 DurationReporter duration_reporter("DUMP ROUTE TABLES");
4431 if (PropertiesHelper::IsDryRun()) return;
4432 const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
4433 ds.DumpFile("RT_TABLES", RT_TABLES_PATH);
4434 FILE* fp = fopen(RT_TABLES_PATH, "re");
4435 if (!fp) {
4436 printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
4437 return;
4438 }
4439 char table[16];
4440 // Each line has an integer (the table number), a space, and a string (the table name). We only
4441 // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
4442 // Add a fixed max limit so this doesn't go awry.
4443 for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
4444 RunCommand("ROUTE TABLE IPv4", {"ip", "-4", "route", "show", "table", table});
4445 RunCommand("ROUTE TABLE IPv6", {"ip", "-6", "route", "show", "table", table});
4446 }
4447 fclose(fp);
4448}
4449
Li Li830179f2022-01-04 12:53:29 -08004450void dump_frozen_cgroupfs(const char *dir, int level,
4451 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4452 DIR *dirp;
4453 struct dirent *d;
4454 char *newpath = nullptr;
4455
4456 dirp = opendir(dir);
4457 if (dirp == nullptr) {
4458 MYLOGE("%s: %s\n", dir, strerror(errno));
4459 return;
4460 }
4461
4462 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4463 if ((d->d_name[0] == '.')
4464 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4465 || (d->d_name[1] == '\0'))) {
4466 continue;
4467 }
4468 if (d->d_type == DT_DIR) {
4469 asprintf(&newpath, "%s/%s/", dir, d->d_name);
4470 if (!newpath) {
4471 continue;
4472 }
4473 if (level == 0 && !strncmp(d->d_name, "uid_", 4)) {
4474 dump_frozen_cgroupfs(newpath, 1, dump_from_fd);
4475 } else if (level == 1 && !strncmp(d->d_name, "pid_", 4)) {
4476 char *freezer = nullptr;
4477 asprintf(&freezer, "%s/%s", newpath, "cgroup.freeze");
4478 if (freezer) {
4479 FILE* fp = fopen(freezer, "r");
4480 if (fp != NULL) {
4481 int frozen;
4482 fscanf(fp, "%d", &frozen);
4483 if (frozen > 0) {
4484 dump_files("", newpath, skip_none, dump_from_fd);
4485 }
4486 fclose(fp);
4487 }
4488 free(freezer);
4489 }
4490 }
4491 }
4492 }
4493 closedir(dirp);
4494}
4495
4496void dump_frozen_cgroupfs() {
Li Li830179f2022-01-04 12:53:29 -08004497 MYLOGD("Adding frozen processes from %s\n", CGROUPFS_DIR);
4498 DurationReporter duration_reporter("FROZEN CGROUPFS");
4499 if (PropertiesHelper::IsDryRun()) return;
4500 dump_frozen_cgroupfs(CGROUPFS_DIR, 0, _add_file_from_fd);
4501}
4502
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004503void Dumpstate::UpdateProgress(int32_t delta_sec) {
4504 if (progress_ == nullptr) {
4505 MYLOGE("UpdateProgress: progress_ not set\n");
4506 return;
4507 }
Rhed Jaobf63d8a2020-07-21 15:42:55 +08004508 // This function updates progress related members of the dumpstate and reports
4509 // progress percentage to the bugreport client. Since it could be called by
4510 // different dump tasks at the same time if the parallel run is enabled, a
4511 // mutex lock is necessary here to synchronize the call.
4512 std::lock_guard<std::recursive_mutex> lock(mutex_);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004513
4514 // Always update progess so stats can be tuned...
Nandana Dutt402a8392019-06-14 14:25:13 +01004515 progress_->Inc(delta_sec);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004516
4517 // ...but only notifiy listeners when necessary.
4518 if (!options_->do_progress_updates) return;
4519
4520 int progress = progress_->Get();
4521 int max = progress_->GetMax();
Nandana Dutt402a8392019-06-14 14:25:13 +01004522 int percent = 100 * progress / max;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004523
Nandana Dutt402a8392019-06-14 14:25:13 +01004524 if (last_reported_percent_progress_ > 0 && percent <= last_reported_percent_progress_) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004525 return;
4526 }
Nandana Dutt402a8392019-06-14 14:25:13 +01004527 last_reported_percent_progress_ = percent;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004528
4529 if (control_socket_fd_ >= 0) {
4530 dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
4531 fsync(control_socket_fd_);
4532 }
4533
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004534 if (listener_ != nullptr) {
Nandana Dutt235c6672019-11-14 15:22:32 +00004535 if (percent % 10 == 0) {
4536 // We don't want to spam logcat, so only log multiples of 10.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004537 MYLOGD("Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004538 } else {
4539 // stderr is ignored on normal invocations, but useful when calling
4540 // /system/bin/dumpstate directly for debuggging.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004541 fprintf(stderr, "Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004542 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004543
4544 listener_->onProgress(percent);
4545 }
4546}
4547
4548void Dumpstate::TakeScreenshot(const std::string& path) {
4549 const std::string& real_path = path.empty() ? screenshot_path_ : path;
4550 int status =
4551 RunCommand("", {"/system/bin/screencap", "-p", real_path},
4552 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
4553 if (status == 0) {
4554 MYLOGD("Screenshot saved on %s\n", real_path.c_str());
4555 } else {
4556 MYLOGE("Failed to take screenshot on %s\n", real_path.c_str());
4557 }
Paul Chang0d2aad72020-02-13 20:04:03 +08004558 if (listener_ != nullptr) {
4559 // Show a visual indication to indicate screenshot is taken via
4560 // IDumpstateListener.onScreenshotTaken()
4561 listener_->onScreenshotTaken(status == 0);
4562 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004563}
4564
4565bool is_dir(const char* pathname) {
4566 struct stat info;
4567 if (stat(pathname, &info) == -1) {
4568 return false;
4569 }
4570 return S_ISDIR(info.st_mode);
4571}
4572
4573time_t get_mtime(int fd, time_t default_mtime) {
4574 struct stat info;
4575 if (fstat(fd, &info) == -1) {
4576 return default_mtime;
4577 }
4578 return info.st_mtime;
4579}