blob: 6d155aa9c3131b2219536f0371d5ffd8ffd35a20 [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
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -070020#include <dirent.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070021#include <errno.h>
22#include <fcntl.h>
Nikita Ioffea325a572019-05-16 19:49:47 +010023#include <inttypes.h>
Felipe Lemead5f6c42015-11-30 14:26:46 -080024#include <libgen.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070025#include <limits.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010026#include <math.h>
27#include <poll.h>
Mark Salyzyn8f37aa52015-06-12 12:28:24 -070028#include <stdbool.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070029#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -070032#include <sys/mount.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080033#include <sys/poll.h>
Christopher Ferris7dc7f322014-07-22 16:08:19 -070034#include <sys/prctl.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070035#include <sys/resource.h>
36#include <sys/stat.h>
37#include <sys/time.h>
38#include <sys/wait.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010039#include <signal.h>
40#include <stdarg.h>
41#include <string.h>
42#include <sys/capability.h>
43#include <sys/inotify.h>
44#include <sys/klog.h>
45#include <time.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070046#include <unistd.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070047
48#include <chrono>
Hridya Valsarajuac582cd2019-08-05 15:39:54 -070049#include <cmath>
Abhijeet Kaurd3cca0d2019-03-25 12:04:16 +000050#include <fstream>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070051#include <functional>
52#include <future>
Narayan Kamath8f788292017-05-25 13:20:39 +010053#include <memory>
Hridya Valsarajuac582cd2019-08-05 15:39:54 -070054#include <numeric>
Narayan Kamath8f788292017-05-25 13:20:39 +010055#include <regex>
56#include <set>
57#include <string>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070058#include <utility>
Narayan Kamath8f788292017-05-25 13:20:39 +010059#include <vector>
Colin Crossf45fa6b2012-03-26 12:38:26 -070060
Kedar Chitnis9fd8c052021-11-16 09:09:22 +000061#include <aidl/android/hardware/dumpstate/IDumpstateDevice.h>
Felipe Leme96c2bbb2016-09-26 09:21:21 -070062#include <android-base/file.h>
63#include <android-base/properties.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070064#include <android-base/scopeguard.h>
Elliott Hughes9dc117c2015-12-07 14:21:50 -080065#include <android-base/stringprintf.h>
Naveen Kalla058e1e82016-10-19 21:38:44 -070066#include <android-base/strings.h>
Andreas Gampeaff68432016-07-18 18:01:27 -070067#include <android-base/unique_fd.h>
Kedar Chitnis9fd8c052021-11-16 09:09:22 +000068#include <android/binder_manager.h>
69#include <android/binder_process.h>
Nikita Ioffea325a572019-05-16 19:49:47 +010070#include <android/content/pm/IPackageManagerNative.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080071#include <android/hardware/dumpstate/1.0/IDumpstateDevice.h>
Hunter Knepshield8540faf2020-02-04 19:47:20 -080072#include <android/hardware/dumpstate/1.1/IDumpstateDevice.h>
73#include <android/hardware/dumpstate/1.1/types.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080074#include <android/hidl/manager/1.0/IServiceManager.h>
Nandana Duttd2f5f082019-01-18 17:13:52 +000075#include <android/os/IIncidentCompanion.h>
Nikita Ioffea325a572019-05-16 19:49:47 +010076#include <binder/IServiceManager.h>
Nikhil Kumar28ce35e2023-01-10 14:32:44 +000077#include <cutils/multiuser.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080078#include <cutils/native_handle.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070079#include <cutils/properties.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010080#include <cutils/sockets.h>
Kevin Jeon2c02e8e2022-07-07 21:45:17 +000081#include <cutils/trace.h>
Nandana Duttfaafd522019-03-11 09:23:09 +000082#include <debuggerd/client.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080083#include <dumpsys.h>
Nandana Duttfaafd522019-03-11 09:23:09 +000084#include <dumputils/dump_utils.h>
Sahana Raof35ed432019-07-12 10:47:52 +010085#include <hardware_legacy/power.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080086#include <hidl/ServiceManagement.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010087#include <log/log.h>
Tom Cherryf4472f32020-08-05 09:31:17 -070088#include <log/log_read.h>
Felipe Leme75876a22016-10-27 16:31:27 -070089#include <openssl/sha.h>
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070090#include <private/android_filesystem_config.h>
91#include <private/android_logger.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080092#include <serviceutils/PriorityDumper.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070093#include <utils/StrongPointer.h>
Devin Moore8df81bb2022-06-08 22:47:02 +000094#include <vintf/VintfObject.h>
Felipe Lemef0292972016-11-22 13:57:05 -080095#include "DumpstateInternal.h"
Felipe Leme75876a22016-10-27 16:31:27 -070096#include "DumpstateService.h"
Colin Crossf45fa6b2012-03-26 12:38:26 -070097#include "dumpstate.h"
Felipe Leme6e01fa62015-11-11 19:35:14 -080098
Kedar Chitnis9fd8c052021-11-16 09:09:22 +000099namespace dumpstate_hal_hidl_1_0 = android::hardware::dumpstate::V1_0;
100namespace dumpstate_hal_hidl = android::hardware::dumpstate::V1_1;
101namespace dumpstate_hal_aidl = aidl::android::hardware::dumpstate;
102
Vishnu Naire97d6122018-01-18 13:58:56 -0800103using ::std::literals::chrono_literals::operator""ms;
104using ::std::literals::chrono_literals::operator""s;
Rhed Jao5377d792020-07-16 17:37:39 +0800105using ::std::placeholders::_1;
Steven Morelandcb7ef822016-11-29 13:20:37 -0800106
Felipe Leme47e9be22016-12-21 15:37:07 -0800107// TODO: remove once moved to namespace
Vishnu Naire97d6122018-01-18 13:58:56 -0800108using android::defaultServiceManager;
109using android::Dumpsys;
110using android::INVALID_OPERATION;
111using android::IServiceManager;
112using android::OK;
113using android::sp;
114using android::status_t;
115using android::String16;
116using android::String8;
117using android::TIMED_OUT;
118using android::UNKNOWN_ERROR;
119using android::Vector;
Nandana Dutt979388e2018-11-30 16:48:55 +0000120using android::base::StringPrintf;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000121using android::os::IDumpstateListener;
Felipe Leme47e9be22016-12-21 15:37:07 -0800122using android::os::dumpstate::CommandOptions;
123using android::os::dumpstate::DumpFileToFd;
Rhed Jao5377d792020-07-16 17:37:39 +0800124using android::os::dumpstate::DumpPool;
Vishnu Naire97d6122018-01-18 13:58:56 -0800125using android::os::dumpstate::PropertiesHelper;
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800126using android::os::dumpstate::TaskQueue;
Chris Morinbc223142022-02-04 14:17:11 -0800127using android::os::dumpstate::WaitForTask;
Felipe Leme47e9be22016-12-21 15:37:07 -0800128
Abhijeet Kaurcf234e82019-07-01 14:53:55 +0100129// Keep in sync with
130// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
131static const int TRACE_DUMP_TIMEOUT_MS = 10000; // 10 seconds
132
133/* Most simple commands have 10 as timeout, so 5 is a good estimate */
134static const int32_t WEIGHT_FILE = 5;
135
136// TODO: temporary variables and functions used during C++ refactoring
137static Dumpstate& ds = Dumpstate::GetInstance();
138static int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Nandana Dutt8d945c02019-08-14 13:30:07 +0100139 const CommandOptions& options = CommandOptions::DEFAULT,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800140 bool verbose_duration = false, int out_fd = STDOUT_FILENO) {
141 return ds.RunCommand(title, full_command, options, verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +0100142}
143
144// Reasonable value for max stats.
145static const int STATS_MAX_N_RUNS = 1000;
146static const long STATS_MAX_AVERAGE = 100000;
147
148CommandOptions Dumpstate::DEFAULT_DUMPSYS = CommandOptions::WithTimeout(30).Build();
149
Nandana Duttd2f5f082019-01-18 17:13:52 +0000150typedef Dumpstate::ConsentCallback::ConsentResult UserConsentResult;
151
Colin Crossf45fa6b2012-03-26 12:38:26 -0700152/* read before root is shed */
153static char cmdline_buf[16384] = "(unknown)";
Yi Kong19d5c002018-07-20 13:39:55 -0700154static const char *dump_traces_path = nullptr;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000155static const uint64_t USER_CONSENT_TIMEOUT_MS = 30 * 1000;
Hunter Knepshield70610fa2020-01-03 15:27:33 -0800156// Because telephony reports are significantly faster to collect (< 10 seconds vs. > 2 minutes),
157// it's often the case that they time out far too quickly for consent with such a hefty dialog for
158// the user to read. For telephony reports only, we increase the default timeout to 2 minutes to
159// roughly match full reports' durations.
160static const uint64_t TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS = 2 * 60 * 1000;
Colin Crossf45fa6b2012-03-26 12:38:26 -0700161
Felipe Leme1d486fe2016-10-14 18:06:47 -0700162// TODO: variables and functions below should be part of dumpstate object
163
Felipe Leme635ca312016-01-05 14:23:02 -0800164static std::set<std::string> mount_points;
165void add_mountinfo();
Felipe Leme78f2c862015-12-21 09:55:22 -0800166
Todd Poynor2a83daa2013-11-22 15:44:22 -0800167#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
Mark Salyzyn7d0a7622016-06-24 14:06:15 -0700168#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
Wei Wang509bb5d2017-06-09 14:42:12 -0700169#define BLK_DEV_SYS_DIR "/sys/block"
Todd Poynor2a83daa2013-11-22 15:44:22 -0800170
Felipe Lemee82a27d2016-01-05 13:35:44 -0800171#define RECOVERY_DIR "/cache/recovery"
Mark Salyzynd6ab0112016-03-25 12:56:39 -0700172#define RECOVERY_DATA_DIR "/data/misc/recovery"
Tianjie Xu75d53362018-04-11 16:42:28 -0700173#define UPDATE_ENGINE_LOG_DIR "/data/misc/update_engine_log"
Kelvin Zhang6eaa0f92022-09-12 09:29:19 -0700174#define UPDATE_ENGINE_PREF_DIR "/data/misc/update_engine/prefs"
Mark Salyzyn4d42dea2016-04-01 10:03:14 -0700175#define LOGPERSIST_DATA_DIR "/data/misc/logd"
Jerry Changa1df8a92020-01-02 16:03:39 +0800176#define PREREBOOT_DATA_DIR "/data/misc/prereboot"
David Brazdild2991962016-06-03 14:40:44 +0100177#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
178#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
Benedict Wong8f9d8a42019-01-03 16:19:38 -0800179#define XFRM_STAT_PROC_FILE "/proc/net/xfrm_stat"
Steven Moreland9379c462023-12-21 02:04:27 +0000180#define KERNEL_CONFIG "/proc/config.gz"
Erik Kline08165202016-05-30 11:55:44 +0900181#define WLUTIL "/vendor/xbin/wlutil"
Vishnu Nair36b4cdb2017-11-17 10:27:05 -0800182#define WMTRACE_DATA_DIR "/data/misc/wmtrace"
Yifan Hong3945e1b2019-10-29 12:59:23 -0700183#define OTA_METADATA_DIR "/metadata/ota"
Yifan Hong0efa7972020-02-03 16:45:02 -0800184#define SNAPSHOTCTL_LOG_DIR "/data/misc/snapshotctl_log"
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +0900185#define LINKERCONFIG_DIR "/linkerconfig"
Calin Juravlef84d3692020-04-28 15:31:12 -0700186#define PACKAGE_DEX_USE_LIST "/data/system/package-dex-usage.list"
Primiano Tuccifaaaafb2021-01-14 12:26:29 +0000187#define SYSTEM_TRACE_SNAPSHOT "/data/misc/perfetto-traces/bugreport/systrace.pftrace"
Li Li2eedd412021-06-30 15:11:53 -0700188#define CGROUPFS_DIR "/sys/fs/cgroup"
Mårten Kongstad60195a72022-09-20 14:14:20 +0200189#define SDK_EXT_INFO "/apex/com.android.sdkext/bin/derive_sdk"
Jeff Sharkey9df29d52023-02-06 14:26:30 -0700190#define DROPBOX_DIR "/data/system/dropbox"
Mårten Kongstad5ad813f2023-09-28 10:09:18 +0200191#define PRINT_FLAGS "/system/bin/printflags"
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700192
Narayan Kamath8f788292017-05-25 13:20:39 +0100193// TODO(narayan): Since this information has to be kept in sync
194// with tombstoned, we should just put it in a common header.
195//
196// File: system/core/debuggerd/tombstoned/tombstoned.cpp
Narayan Kamathbd863722017-06-01 18:50:12 +0100197static const std::string TOMBSTONE_DIR = "/data/tombstones/";
198static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
199static const std::string ANR_DIR = "/data/anr/";
200static const std::string ANR_FILE_PREFIX = "anr_";
Andy Hungd62f7e62024-01-11 15:47:52 -0800201static const std::string ANR_TRACE_FILE_PREFIX = "trace_";
Woody Lin20767a92022-11-29 15:50:24 +0800202static const std::string SHUTDOWN_CHECKPOINTS_DIR = "/data/system/shutdown-checkpoints/";
203static const std::string SHUTDOWN_CHECKPOINTS_FILE_PREFIX = "checkpoints-";
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700204
Felipe Lemee844a9d2016-09-21 15:01:39 -0700205// TODO: temporary variables and functions used during C++ refactoring
Nandana Dutt979388e2018-11-30 16:48:55 +0000206
Nandana Dutt5c390032019-03-12 10:52:56 +0000207#define RETURN_IF_USER_DENIED_CONSENT() \
208 if (ds.IsUserConsentDenied()) { \
209 MYLOGE("Returning early as user denied consent to share bugreport with calling app."); \
210 return Dumpstate::RunStatus::USER_CONSENT_DENIED; \
211 }
212
213// Runs func_ptr, but checks user consent before and after running it. Returns USER_CONSENT_DENIED
214// if consent is found to be denied.
215#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(func_ptr, ...) \
216 RETURN_IF_USER_DENIED_CONSENT(); \
217 func_ptr(__VA_ARGS__); \
218 RETURN_IF_USER_DENIED_CONSENT();
219
Rhed Jao5377d792020-07-16 17:37:39 +0800220// Runs func_ptr, and logs a duration report after it's finished.
221#define RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, ...) \
222 { \
223 DurationReporter duration_reporter_in_macro(log_title); \
224 func_ptr(__VA_ARGS__); \
225 }
226
227// Similar with RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK, an additional duration report
228// is output after a slow function is finished.
229#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(log_title, func_ptr, ...) \
230 RETURN_IF_USER_DENIED_CONSENT(); \
231 RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, __VA_ARGS__); \
232 RETURN_IF_USER_DENIED_CONSENT();
233
Chris Morinbc223142022-02-04 14:17:11 -0800234#define WAIT_TASK_WITH_CONSENT_CHECK(future) \
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800235 RETURN_IF_USER_DENIED_CONSENT(); \
Chris Morinbc223142022-02-04 14:17:11 -0800236 WaitForTask(future); \
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800237 RETURN_IF_USER_DENIED_CONSENT();
238
Sahana Raof35ed432019-07-12 10:47:52 +0100239static const char* WAKE_LOCK_NAME = "dumpstate_wakelock";
240
Rhed Jao5377d792020-07-16 17:37:39 +0800241// Names of parallel tasks, they are used for the DumpPool to identify the dump
242// task and the log title of the duration report.
243static const std::string DUMP_TRACES_TASK = "DUMP TRACES";
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800244static const std::string DUMP_INCIDENT_REPORT_TASK = "INCIDENT REPORT";
Aaron Huanga99452a2022-04-27 18:51:16 +0800245static const std::string DUMP_NETSTATS_PROTO_TASK = "DUMP NETSTATS PROTO";
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800246static const std::string DUMP_HALS_TASK = "DUMP HALS";
247static const std::string DUMP_BOARD_TASK = "dumpstate_board()";
Rhed Jaoe017f982020-07-21 17:58:41 +0800248static const std::string DUMP_CHECKINS_TASK = "DUMP CHECKINS";
Kean Mariotti306633e2022-09-05 16:30:47 +0000249static const std::string POST_PROCESS_UI_TRACES_TASK = "POST-PROCESS UI TRACES";
Rhed Jao5377d792020-07-16 17:37:39 +0800250
Nandana Dutt979388e2018-11-30 16:48:55 +0000251namespace android {
252namespace os {
253namespace {
254
255static int Open(std::string path, int flags, mode_t mode = 0) {
256 int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
257 if (fd == -1) {
258 MYLOGE("open(%s, %s)\n", path.c_str(), strerror(errno));
259 }
260 return fd;
261}
262
mhasank2d75c442020-06-11 15:05:25 -0700263static int OpenForWrite(std::string path) {
264 return Open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
265 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
266}
Nandana Dutt979388e2018-11-30 16:48:55 +0000267
268static int OpenForRead(std::string path) {
269 return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
270}
271
272bool CopyFile(int in_fd, int out_fd) {
273 char buf[4096];
274 ssize_t byte_count;
275 while ((byte_count = TEMP_FAILURE_RETRY(read(in_fd, buf, sizeof(buf)))) > 0) {
276 if (!android::base::WriteFully(out_fd, buf, byte_count)) {
277 return false;
278 }
279 }
280 return (byte_count != -1);
281}
282
283static bool CopyFileToFd(const std::string& input_file, int out_fd) {
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000284 MYLOGD("Going to copy file (%s) to %d\n", input_file.c_str(), out_fd);
Nandana Dutt979388e2018-11-30 16:48:55 +0000285
286 // Obtain a handle to the source file.
287 android::base::unique_fd in_fd(OpenForRead(input_file));
288 if (out_fd != -1 && in_fd.get() != -1) {
289 if (CopyFile(in_fd.get(), out_fd)) {
290 return true;
291 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000292 MYLOGE("Failed to copy file: %s\n", strerror(errno));
Nandana Dutt979388e2018-11-30 16:48:55 +0000293 }
294 return false;
295}
296
Nandana Duttd2f5f082019-01-18 17:13:52 +0000297static bool UnlinkAndLogOnError(const std::string& file) {
Nandana Dutt8ae16e62020-03-27 10:20:22 +0000298 if (file.empty()) {
299 return false;
300 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000301 if (unlink(file.c_str())) {
302 MYLOGE("Failed to unlink file (%s): %s\n", file.c_str(), strerror(errno));
Nandana Duttd2f5f082019-01-18 17:13:52 +0000303 return false;
304 }
305 return true;
306}
Nandana Dutt979388e2018-11-30 16:48:55 +0000307
Nikita Ioffea325a572019-05-16 19:49:47 +0100308int64_t GetModuleMetadataVersion() {
309 auto binder = defaultServiceManager()->getService(android::String16("package_native"));
310 if (binder == nullptr) {
311 MYLOGE("Failed to retrieve package_native service");
312 return 0L;
313 }
314 auto package_service = android::interface_cast<content::pm::IPackageManagerNative>(binder);
315 std::string package_name;
316 auto status = package_service->getModuleMetadataPackageName(&package_name);
317 if (!status.isOk()) {
318 MYLOGE("Failed to retrieve module metadata package name: %s", status.toString8().c_str());
319 return 0L;
320 }
Nandana Duttdb379fa2019-10-09 16:54:41 +0100321 MYLOGD("Module metadata package name: %s\n", package_name.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100322 int64_t version_code;
323 status = package_service->getVersionCodeForPackage(android::String16(package_name.c_str()),
324 &version_code);
325 if (!status.isOk()) {
326 MYLOGE("Failed to retrieve module metadata version: %s", status.toString8().c_str());
327 return 0L;
328 }
329 return version_code;
330}
331
mhasank2d75c442020-06-11 15:05:25 -0700332static bool PathExists(const std::string& path) {
333 struct stat sb;
334 return stat(path.c_str(), &sb) == 0;
335}
336
337static bool CopyFileToFile(const std::string& input_file, const std::string& output_file) {
338 if (input_file == output_file) {
339 MYLOGD("Skipping copying bugreport file since the destination is the same (%s)\n",
340 output_file.c_str());
341 return false;
342 }
343 else if (PathExists(output_file)) {
344 MYLOGD("Cannot overwrite an existing file (%s)\n", output_file.c_str());
345 return false;
346 }
347
348 MYLOGD("Going to copy bugreport file (%s) to %s\n", input_file.c_str(), output_file.c_str());
349 android::base::unique_fd out_fd(OpenForWrite(output_file));
350 return CopyFileToFd(input_file, out_fd.get());
351}
352
Nandana Dutt979388e2018-11-30 16:48:55 +0000353} // namespace
354} // namespace os
355} // namespace android
356
Felipe Leme678727a2016-09-21 17:22:11 -0700357static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
Felipe Lemebda15a02016-11-16 17:48:25 -0800358 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
Rhed Jaoe017f982020-07-21 17:58:41 +0800359 long dumpsysTimeoutMs = 0, int out_fd = STDOUT_FILENO) {
360 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs, out_fd);
361}
362static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
363 int out_fd) {
364 return ds.RunDumpsys(title, dumpsysArgs, Dumpstate::DEFAULT_DUMPSYS, 0, out_fd);
Felipe Leme678727a2016-09-21 17:22:11 -0700365}
366static int DumpFile(const std::string& title, const std::string& path) {
367 return ds.DumpFile(title, path);
368}
Felipe Lemee82a27d2016-01-05 13:35:44 -0800369
Felipe Lemee844a9d2016-09-21 15:01:39 -0700370// Relative directory (inside the zip) for all files copied as-is into the bugreport.
371static const std::string ZIP_ROOT_DIR = "FS";
372
Vishnu Naire97d6122018-01-18 13:58:56 -0800373static const std::string kProtoPath = "proto/";
374static const std::string kProtoExt = ".proto";
Jie Song9fbfad02017-06-20 16:29:42 -0700375static const std::string kDumpstateBoardFiles[] = {
376 "dumpstate_board.txt",
Felipe Leme95d6ca52017-08-01 16:35:56 -0700377 "dumpstate_board.bin"
Jie Song9fbfad02017-06-20 16:29:42 -0700378};
379static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
380
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700381static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Lemed071c682016-10-20 16:48:00 -0700382static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700383
Felipe Lemef0292972016-11-22 13:57:05 -0800384static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
385
Narayan Kamath8f788292017-05-25 13:20:39 +0100386/*
Narayan Kamathbd863722017-06-01 18:50:12 +0100387 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
Rhed Jao01dc0c62020-06-03 17:13:30 +0800388 * The returned vector is sorted by the mtimes of the dumps with descending
Chris Morinc2cba7a2022-02-01 17:06:50 -0800389 * order.
Narayan Kamath8f788292017-05-25 13:20:39 +0100390 */
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700391static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
Chris Morinc2cba7a2022-02-01 17:06:50 -0800392 const std::string& file_prefix) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100393 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100394
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700395 if (dump_dir == nullptr) {
396 MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno));
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700397 return std::vector<DumpData>();
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700398 }
399
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700400 std::vector<DumpData> dump_data;
Narayan Kamathbd863722017-06-01 18:50:12 +0100401 struct dirent* entry = nullptr;
402 while ((entry = readdir(dump_dir.get()))) {
403 if (entry->d_type != DT_REG) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100404 continue;
405 }
406
Narayan Kamathbd863722017-06-01 18:50:12 +0100407 const std::string base_name(entry->d_name);
408 if (base_name.find(file_prefix) != 0) {
409 continue;
410 }
411
412 const std::string abs_path = dir_path + base_name;
413 android::base::unique_fd fd(
414 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
415 if (fd == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700416 MYLOGW("Unable to open dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamathbd863722017-06-01 18:50:12 +0100417 break;
418 }
419
420 struct stat st = {};
421 if (fstat(fd, &st) == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700422 MYLOGW("Unable to stat dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamath8f788292017-05-25 13:20:39 +0100423 continue;
424 }
425
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700426 dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700427 }
Rhed Jao01dc0c62020-06-03 17:13:30 +0800428 if (!dump_data.empty()) {
429 std::sort(dump_data.begin(), dump_data.end(),
430 [](const auto& a, const auto& b) { return a.mtime > b.mtime; });
431 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100432
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700433 return dump_data;
Narayan Kamath8f788292017-05-25 13:20:39 +0100434}
435
Narayan Kamathbd863722017-06-01 18:50:12 +0100436static bool AddDumps(const std::vector<DumpData>::const_iterator start,
437 const std::vector<DumpData>::const_iterator end,
438 const char* type_name, const bool add_to_zip) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100439 bool dumped = false;
Narayan Kamathbd863722017-06-01 18:50:12 +0100440 for (auto it = start; it != end; ++it) {
441 const std::string& name = it->name;
442 const int fd = it->fd;
Narayan Kamath8f788292017-05-25 13:20:39 +0100443 dumped = true;
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100444
445 // Seek to the beginning of the file before dumping any data. A given
446 // DumpData entry might be dumped multiple times in the report.
447 //
448 // For example, the most recent ANR entry is dumped to the body of the
449 // main entry and it also shows up as a separate entry in the bugreport
450 // ZIP file.
451 if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) {
452 MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(),
453 strerror(errno));
454 }
455
Chris Morinc2cba7a2022-02-01 17:06:50 -0800456 if (add_to_zip) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800457 if (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd, /* timeout = */ 0ms) != OK) {
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100458 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100459 }
460 } else {
461 dump_file_from_fd(type_name, name.c_str(), fd);
462 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100463 }
464
465 return dumped;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700466}
467
Felipe Leme635ca312016-01-05 14:23:02 -0800468// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700469void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800470 char path[PATH_MAX];
471
472 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
473 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700474 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800475 char linkname[PATH_MAX];
476 ssize_t r = readlink(path, linkname, PATH_MAX);
477 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800478 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800479 return;
480 }
481 linkname[r] = '\0';
482
483 if (mount_points.find(linkname) == mount_points.end()) {
484 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700485 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700486 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
Felipe Leme635ca312016-01-05 14:23:02 -0800487 mount_points.insert(linkname);
488 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800489 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800490 }
491 }
492}
493
494void add_mountinfo() {
Felipe Leme678727a2016-09-21 17:22:11 -0700495 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800496 mount_points.clear();
Felipe Leme46b85da2016-11-21 17:40:45 -0800497 DurationReporter duration_reporter(title, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700498 for_each_pid(do_mountinfo, nullptr);
499 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800500}
501
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700502static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
503{
504 DIR *d;
505 struct dirent *de;
506 char path[PATH_MAX];
507
508 d = opendir(driverpath);
Yi Kong19d5c002018-07-20 13:39:55 -0700509 if (d == nullptr) {
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700510 return;
511 }
512
513 while ((de = readdir(d))) {
514 if (de->d_type != DT_LNK) {
515 continue;
516 }
517 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700518 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700519 }
520
521 closedir(d);
522}
523
Mark Salyzyn326842f2015-04-30 09:49:41 -0700524static bool skip_not_stat(const char *path) {
525 static const char stat[] = "/stat";
526 size_t len = strlen(path);
527 if (path[len - 1] == '/') { /* Directory? */
528 return false;
529 }
530 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
531}
532
Jeff Sharkey9df29d52023-02-06 14:26:30 -0700533static bool skip_wtf_strictmode(const char *path) {
534 if (strstr(path, "_wtf")) {
535 return true;
536 } else if (strstr(path, "_strictmode")) {
537 return true;
538 }
539 return false;
540}
541
Felipe Leme4c2d6632016-09-28 14:32:00 -0700542static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800543 return false;
544}
545
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700546unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700547
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800548//
549// stat offsets
550// Name units description
551// ---- ----- -----------
552// read I/Os requests number of read I/Os processed
553#define __STAT_READ_IOS 0
554// read merges requests number of read I/Os merged with in-queue I/O
555#define __STAT_READ_MERGES 1
556// read sectors sectors number of sectors read
557#define __STAT_READ_SECTORS 2
558// read ticks milliseconds total wait time for read requests
559#define __STAT_READ_TICKS 3
560// write I/Os requests number of write I/Os processed
561#define __STAT_WRITE_IOS 4
562// write merges requests number of write I/Os merged with in-queue I/O
563#define __STAT_WRITE_MERGES 5
564// write sectors sectors number of sectors written
565#define __STAT_WRITE_SECTORS 6
566// write ticks milliseconds total wait time for write requests
567#define __STAT_WRITE_TICKS 7
568// in_flight requests number of I/Os currently in flight
569#define __STAT_IN_FLIGHT 8
570// io_ticks milliseconds total time this block device has been active
571#define __STAT_IO_TICKS 9
572// time_in_queue milliseconds total wait time for all requests
573#define __STAT_IN_QUEUE 10
574#define __STAT_NUMBER_FIELD 11
575//
576// read I/Os, write I/Os
577// =====================
578//
579// These values increment when an I/O request completes.
580//
581// read merges, write merges
582// =========================
583//
584// These values increment when an I/O request is merged with an
585// already-queued I/O request.
586//
587// read sectors, write sectors
588// ===========================
589//
590// These values count the number of sectors read from or written to this
591// block device. The "sectors" in question are the standard UNIX 512-byte
592// sectors, not any device- or filesystem-specific block size. The
593// counters are incremented when the I/O completes.
594#define SECTOR_SIZE 512
595//
596// read ticks, write ticks
597// =======================
598//
599// These values count the number of milliseconds that I/O requests have
600// waited on this block device. If there are multiple I/O requests waiting,
601// these values will increase at a rate greater than 1000/second; for
602// example, if 60 read requests wait for an average of 30 ms, the read_ticks
603// field will increase by 60*30 = 1800.
604//
605// in_flight
606// =========
607//
608// This value counts the number of I/O requests that have been issued to
609// the device driver but have not yet completed. It does not include I/O
610// requests that are in the queue but not yet issued to the device driver.
611//
612// io_ticks
613// ========
614//
615// This value counts the number of milliseconds during which the device has
616// had I/O requests queued.
617//
618// time_in_queue
619// =============
620//
621// This value counts the number of milliseconds that I/O requests have waited
622// on this block device. If there are multiple I/O requests waiting, this
623// value will increase as the product of the number of milliseconds times the
624// number of requests waiting (see "read ticks" above for an example).
625#define S_TO_MS 1000
626//
627
Mark Salyzyn326842f2015-04-30 09:49:41 -0700628static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800629 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700630 bool z;
Yi Kong19d5c002018-07-20 13:39:55 -0700631 char *cp, *buffer = nullptr;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700632 size_t i = 0;
Josh Gao7c4258c2018-06-25 13:40:08 -0700633 FILE *fp = fdopen(dup(fd), "rb");
Mark Salyzyn326842f2015-04-30 09:49:41 -0700634 getline(&buffer, &i, fp);
635 fclose(fp);
636 if (!buffer) {
637 return -errno;
638 }
639 i = strlen(buffer);
640 while ((i > 0) && (buffer[i - 1] == '\n')) {
641 buffer[--i] = '\0';
642 }
643 if (!*buffer) {
644 free(buffer);
645 return 0;
646 }
647 z = true;
648 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800649 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700650 if (fields[i] != 0) {
651 z = false;
652 }
653 }
654 if (z) { /* never accessed */
655 free(buffer);
656 return 0;
657 }
658
Wei Wang509bb5d2017-06-09 14:42:12 -0700659 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
660 path += sizeof(BLK_DEV_SYS_DIR) - 1;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700661 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700662
663 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
664 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
665 "W-wait", "in-fli", "activ", "T-wait", path, buffer);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700666 free(buffer);
667
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800668 if (fields[__STAT_IO_TICKS]) {
669 unsigned long read_perf = 0;
670 unsigned long read_ios = 0;
671 if (fields[__STAT_READ_TICKS]) {
672 unsigned long long divisor = fields[__STAT_READ_TICKS]
673 * fields[__STAT_IO_TICKS];
674 read_perf = ((unsigned long long)SECTOR_SIZE
675 * fields[__STAT_READ_SECTORS]
676 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
677 / divisor;
678 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
679 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
680 / divisor;
681 }
682
683 unsigned long write_perf = 0;
684 unsigned long write_ios = 0;
685 if (fields[__STAT_WRITE_TICKS]) {
686 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
687 * fields[__STAT_IO_TICKS];
688 write_perf = ((unsigned long long)SECTOR_SIZE
689 * fields[__STAT_WRITE_SECTORS]
690 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
691 / divisor;
692 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
693 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
694 / divisor;
695 }
696
697 unsigned queue = (fields[__STAT_IN_QUEUE]
698 + (fields[__STAT_IO_TICKS] >> 1))
699 / fields[__STAT_IO_TICKS];
700
701 if (!write_perf && !write_ios) {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700702 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 -0800703 } else {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700704 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 -0800705 read_ios, write_perf, write_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800706 }
707
708 /* bugreport timeout factor adjustment */
709 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
710 worst_write_perf = write_perf;
711 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700712 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700713 return 0;
714}
715
Yao Chenbe3bbc12018-01-17 16:31:10 -0800716static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
717
Tom Cherryf4472f32020-08-05 09:31:17 -0700718// Returns the actual readable size of the given buffer or -1 on error.
719static long logcat_buffer_readable_size(const std::string& buffer) {
720 std::unique_ptr<logger_list, decltype(&android_logger_list_free)> logger_list{
721 android_logger_list_alloc(0, 0, 0), &android_logger_list_free};
722 auto logger = android_logger_open(logger_list.get(), android_name_to_log_id(buffer.c_str()));
723
724 return android_logger_get_log_readable_size(logger);
725}
726
727// Returns timeout in ms to read a list of buffers.
Yao Chenbe3bbc12018-01-17 16:31:10 -0800728static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
729 unsigned long timeout_ms = 0;
730 for (const auto& buffer : buffers) {
Tom Cherryf4472f32020-08-05 09:31:17 -0700731 long readable_size = logcat_buffer_readable_size(buffer);
732 if (readable_size > 0) {
733 // Engineering margin is ten-fold our guess.
734 timeout_ms += 10 * (readable_size + worst_write_perf) / worst_write_perf;
735 }
Yao Chenbe3bbc12018-01-17 16:31:10 -0800736 }
737 return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700738}
739
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800740// Opens a socket and returns its file descriptor.
741static int open_socket(const char* service);
742
Nandana Duttd2f5f082019-01-18 17:13:52 +0000743Dumpstate::ConsentCallback::ConsentCallback() : result_(UNAVAILABLE), start_time_(Nanotime()) {
744}
745
746android::binder::Status Dumpstate::ConsentCallback::onReportApproved() {
747 std::lock_guard<std::mutex> lock(lock_);
748 result_ = APPROVED;
749 MYLOGD("User approved consent to share bugreport\n");
Paul Chang0d2aad72020-02-13 20:04:03 +0800750
751 // Maybe copy screenshot so calling app can display the screenshot to the user as soon as
752 // consent is granted.
753 if (ds.options_->is_screenshot_copied) {
754 return android::binder::Status::ok();
755 }
756
757 if (!ds.options_->do_screenshot || ds.options_->screenshot_fd.get() == -1 ||
758 !ds.do_early_screenshot_) {
759 return android::binder::Status::ok();
760 }
761
762 bool copy_succeeded = android::os::CopyFileToFd(ds.screenshot_path_,
763 ds.options_->screenshot_fd.get());
764 ds.options_->is_screenshot_copied = copy_succeeded;
765 if (copy_succeeded) {
766 android::os::UnlinkAndLogOnError(ds.screenshot_path_);
767 }
Nandana Duttd2f5f082019-01-18 17:13:52 +0000768 return android::binder::Status::ok();
769}
770
771android::binder::Status Dumpstate::ConsentCallback::onReportDenied() {
772 std::lock_guard<std::mutex> lock(lock_);
773 result_ = DENIED;
774 MYLOGW("User denied consent to share bugreport\n");
775 return android::binder::Status::ok();
776}
777
778UserConsentResult Dumpstate::ConsentCallback::getResult() {
779 std::lock_guard<std::mutex> lock(lock_);
780 return result_;
781}
782
783uint64_t Dumpstate::ConsentCallback::getElapsedTimeMs() const {
Hunter Knepshieldf0a39052020-01-03 14:53:04 -0800784 return (Nanotime() - start_time_) / NANOS_PER_MILLI;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000785}
786
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700787void Dumpstate::PrintHeader() const {
Mårten Kongstad60195a72022-09-20 14:14:20 +0200788 std::string build, fingerprint, radio, bootloader, network, sdkversion;
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700789 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700790
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700791 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
792 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700793 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
794 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
795 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
Mårten Kongstad60195a72022-09-20 14:14:20 +0200796 sdkversion = android::base::GetProperty("ro.build.version.sdk", "(unknown)");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700797 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
Colin Crossf45fa6b2012-03-26 12:38:26 -0700798
Felipe Lemed8b94e52016-12-08 10:21:44 -0800799 printf("========================================================\n");
800 printf("== dumpstate: %s\n", date);
801 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700802
Felipe Lemed8b94e52016-12-08 10:21:44 -0800803 printf("\n");
804 printf("Build: %s\n", build.c_str());
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700805 // NOTE: fingerprint entry format is important for other tools.
Felipe Lemed8b94e52016-12-08 10:21:44 -0800806 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
807 printf("Bootloader: %s\n", bootloader.c_str());
808 printf("Radio: %s\n", radio.c_str());
809 printf("Network: %s\n", network.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100810 int64_t module_metadata_version = android::os::GetModuleMetadataVersion();
811 if (module_metadata_version != 0) {
812 printf("Module Metadata version: %" PRId64 "\n", module_metadata_version);
813 }
Mårten Kongstad60195a72022-09-20 14:14:20 +0200814 printf("Android SDK version: %s\n", sdkversion.c_str());
815 printf("SDK extensions: ");
816 RunCommandToFd(STDOUT_FILENO, "", {SDK_EXT_INFO, "--header"},
817 CommandOptions::WithTimeout(1).Always().DropRoot().Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700818
Felipe Lemed8b94e52016-12-08 10:21:44 -0800819 printf("Kernel: ");
Felipe Lemef0292972016-11-22 13:57:05 -0800820 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
Felipe Lemed8b94e52016-12-08 10:21:44 -0800821 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
Devin Moore09fde8d2023-03-21 16:28:22 +0000822 printf("Bootconfig: ");
823 DumpFileToFd(STDOUT_FILENO, "", "/proc/bootconfig");
Felipe Leme7709f8a2017-12-05 09:30:09 -0800824 printf("Uptime: ");
825 RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"},
826 CommandOptions::WithTimeout(1).Always().Build());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800827 printf("Bugreport format version: %s\n", version_.c_str());
Kevin Jeonfa64e642023-07-27 11:36:41 -0400828 printf(
829 "Dumpstate info: id=%d pid=%d dry_run=%d parallel_run=%d strict_run=%d args=%s "
830 "bugreport_mode=%s\n",
831 id_, pid_, PropertiesHelper::IsDryRun(), PropertiesHelper::IsParallelRun(),
832 PropertiesHelper::IsStrictRun(), options_->args.c_str(),
833 options_->bugreport_mode_string.c_str());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800834 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800835}
836
Felipe Leme24b66ee2016-06-16 10:55:26 -0700837// List of file extensions that can cause a zip file attachment to be rejected by some email
838// service providers.
839static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
840 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
841 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
842 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
843};
844
Vishnu Naire97d6122018-01-18 13:58:56 -0800845status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd,
846 std::chrono::milliseconds timeout = 0ms) {
Felipe Leme24b66ee2016-06-16 10:55:26 -0700847 std::string valid_name = entry_name;
848
849 // Rename extension if necessary.
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -0700850 size_t idx = entry_name.rfind('.');
Felipe Leme24b66ee2016-06-16 10:55:26 -0700851 if (idx != std::string::npos) {
852 std::string extension = entry_name.substr(idx);
853 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
854 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
855 valid_name = entry_name + ".renamed";
856 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
857 }
858 }
859
Felipe Leme6fe9db62016-02-12 09:04:16 -0800860 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
861 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Kevin Jeon9bbe0ac2022-05-05 22:05:43 +0000862 size_t flags = ZipWriter::kCompress | ZipWriter::kDefaultCompression;
863 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), flags,
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700864 get_mtime(fd, ds.now_));
Felipe Leme1d486fe2016-10-14 18:06:47 -0700865 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700866 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700867 ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800868 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800869 }
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000870 bool finished_entry = false;
871 auto finish_entry = [this, &finished_entry] {
872 if (!finished_entry) {
873 // This should only be called when we're going to return an earlier error,
874 // which would've been logged. This may imply the file is already corrupt
875 // and any further logging from FinishEntry is more likely to mislead than
876 // not.
877 this->zip_writer_->FinishEntry();
878 }
879 };
880 auto scope_guard = android::base::make_scope_guard(finish_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -0800881 auto start = std::chrono::steady_clock::now();
882 auto end = start + timeout;
883 struct pollfd pfd = {fd, POLLIN};
Felipe Lemee82a27d2016-01-05 13:35:44 -0800884
Felipe Leme770410d2016-01-26 17:07:14 -0800885 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800886 while (1) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800887 if (timeout.count() > 0) {
888 // lambda to recalculate the timeout.
889 auto time_left_ms = [end]() {
890 auto now = std::chrono::steady_clock::now();
891 auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
892 return std::max(diff.count(), 0LL);
893 };
894
895 int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
896 if (rc < 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000897 MYLOGE("Error in poll while adding from fd to zip entry %s:%s\n",
898 entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800899 return -errno;
900 } else if (rc == 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000901 MYLOGE("Timed out adding from fd to zip entry %s:%s Timeout:%lldms\n",
Vishnu Naire97d6122018-01-18 13:58:56 -0800902 entry_name.c_str(), strerror(errno), timeout.count());
903 return TIMED_OUT;
904 }
905 }
906
Zach Riggle22200402016-08-18 01:01:24 -0400907 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800908 if (bytes_read == 0) {
909 break;
910 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800911 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800912 return -errno;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800913 }
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700914 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800915 if (err) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700916 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800917 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800918 }
919 }
920
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700921 err = zip_writer_->FinishEntry();
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000922 finished_entry = true;
Felipe Leme1d486fe2016-10-14 18:06:47 -0700923 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700924 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800925 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800926 }
927
Vishnu Naire97d6122018-01-18 13:58:56 -0800928 return OK;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800929}
930
Felipe Leme1d486fe2016-10-14 18:06:47 -0700931bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
932 android::base::unique_fd fd(
933 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700934 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800935 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800936 return false;
937 }
938
Vishnu Naire97d6122018-01-18 13:58:56 -0800939 return (AddZipEntryFromFd(entry_name, fd.get()) == OK);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800940}
941
942/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700943static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800944 return (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) == OK) ? 0 : 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800945}
946
Felipe Leme1d486fe2016-10-14 18:06:47 -0700947void Dumpstate::AddDir(const std::string& dir, bool recursive) {
Felipe Leme678727a2016-09-21 17:22:11 -0700948 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
Felipe Leme46b85da2016-11-21 17:40:45 -0800949 DurationReporter duration_reporter(dir, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700950 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800951}
952
Felipe Leme1d486fe2016-10-14 18:06:47 -0700953bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800954 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Kevin Jeon9bbe0ac2022-05-05 22:05:43 +0000955 size_t flags = ZipWriter::kCompress | ZipWriter::kDefaultCompression;
956 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), flags, ds.now_);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700957 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700958 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700959 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800960 return false;
961 }
962
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700963 err = zip_writer_->WriteBytes(content.c_str(), content.length());
Felipe Leme1d486fe2016-10-14 18:06:47 -0700964 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700965 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700966 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800967 return false;
968 }
969
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700970 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700971 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700972 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800973 return false;
974 }
975
976 return true;
977}
978
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800979static void DoKmsg() {
980 struct stat st;
981 if (!stat(PSTORE_LAST_KMSG, &st)) {
982 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
983 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
984 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
985 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
986 } else {
987 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
988 DumpFile("LAST KMSG", "/proc/last_kmsg");
989 }
990}
991
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800992static void DoKernelLogcat() {
Yao Chenbe3bbc12018-01-17 16:31:10 -0800993 unsigned long timeout_ms = logcat_timeout({"kernel"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800994 RunCommand(
995 "KERNEL LOG",
996 {"logcat", "-b", "kernel", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
997 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
998}
999
Nandana Duttdb379fa2019-10-09 16:54:41 +01001000static void DoSystemLogcat(time_t since) {
1001 char since_str[80];
1002 strftime(since_str, sizeof(since_str), "%Y-%m-%d %H:%M:%S.000", localtime(&since));
1003
1004 unsigned long timeout_ms = logcat_timeout({"main", "system", "crash"});
1005 RunCommand("SYSTEM LOG",
1006 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v", "-T",
1007 since_str},
1008 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1009}
1010
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001011static void DoRadioLogcat() {
1012 unsigned long timeout_ms = logcat_timeout({"radio"});
1013 RunCommand(
1014 "RADIO LOG",
1015 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1016 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
1017}
1018
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001019static void DoLogcat() {
Vishnu Nair6921f802017-11-22 09:17:23 -08001020 unsigned long timeout_ms;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001021 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
1022 // calculate timeout
Yao Chenbe3bbc12018-01-17 16:31:10 -08001023 timeout_ms = logcat_timeout({"main", "system", "crash"});
Tony Makae737652017-03-30 17:47:09 +01001024 RunCommand("SYSTEM LOG",
Vishnu Nair6921f802017-11-22 09:17:23 -08001025 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1026 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -08001027 timeout_ms = logcat_timeout({"events"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001028 RunCommand(
1029 "EVENT LOG",
1030 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001031 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Yao Chenbe3bbc12018-01-17 16:31:10 -08001032 timeout_ms = logcat_timeout({"stats"});
1033 RunCommand(
1034 "STATS LOG",
1035 {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001036 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001037 DoRadioLogcat();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001038
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001039 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001040 RunCommand("LAST LOGCAT", {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable",
1041 "-v", "uid", "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001042}
1043
Mike Ma5c267872019-08-21 11:31:34 -07001044static void DumpIncidentReport() {
Mike Ma5c267872019-08-21 11:31:34 -07001045 const std::string path = ds.bugreport_internal_dir_ + "/tmp_incident_report";
1046 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1047 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1048 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1049 if (fd < 0) {
1050 MYLOGE("Could not open %s to dump incident report.\n", path.c_str());
1051 return;
1052 }
Kevin Jeonfa64e642023-07-27 11:36:41 -04001053 RunCommandToFd(fd, "", {"incident", "-u"},
1054 CommandOptions::WithTimeout(PropertiesHelper::IsStrictRun() ? 20 : 120).Build());
Mike Ma5c267872019-08-21 11:31:34 -07001055 bool empty = 0 == lseek(fd, 0, SEEK_END);
1056 if (!empty) {
1057 // Use a different name from "incident.proto"
1058 // /proto/incident.proto is reserved for incident service dump
1059 // i.e. metadata for debugging.
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001060 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "incident_report" + kProtoExt,
1061 path);
1062 } else {
1063 unlink(path.c_str());
Mike Ma5c267872019-08-21 11:31:34 -07001064 }
Mike Ma5c267872019-08-21 11:31:34 -07001065}
1066
Aaron Huanga99452a2022-04-27 18:51:16 +08001067static void DumpNetstatsProto() {
1068 const std::string path = ds.bugreport_internal_dir_ + "/tmp_netstats_proto";
1069 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1070 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1071 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1072 if (fd < 0) {
1073 MYLOGE("Could not open %s to dump netstats proto.\n", path.c_str());
1074 return;
1075 }
1076 RunCommandToFd(fd, "", {"dumpsys", "netstats", "--proto"},
Kevin Jeon2fb3dd62022-09-28 18:48:55 +00001077 CommandOptions::WithTimeout(5).Build());
Aaron Huanga99452a2022-04-27 18:51:16 +08001078 bool empty = 0 == lseek(fd, 0, SEEK_END);
1079 if (!empty) {
1080 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "netstats" + kProtoExt,
1081 path);
1082 } else {
1083 unlink(path.c_str());
1084 }
1085}
1086
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001087static void MaybeAddSystemTraceToZip() {
1088 // This function copies into the .zip the system trace that was snapshotted
1089 // by the early call to MaybeSnapshotSystemTrace(), if any background
1090 // tracing was happening.
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001091 if (!ds.has_system_trace_) {
1092 // No background trace was happening at the time dumpstate was invoked.
1093 return;
1094 }
1095 ds.AddZipEntry(
1096 ZIP_ROOT_DIR + SYSTEM_TRACE_SNAPSHOT,
1097 SYSTEM_TRACE_SNAPSHOT);
1098 android::os::UnlinkAndLogOnError(SYSTEM_TRACE_SNAPSHOT);
1099}
1100
Sunny Goyal35949782019-11-19 15:54:36 -08001101static void DumpVisibleWindowViews() {
Sunny Goyal35949782019-11-19 15:54:36 -08001102 DurationReporter duration_reporter("VISIBLE WINDOW VIEWS");
1103 const std::string path = ds.bugreport_internal_dir_ + "/tmp_visible_window_views";
1104 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1105 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1106 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1107 if (fd < 0) {
1108 MYLOGE("Could not open %s to dump visible views.\n", path.c_str());
1109 return;
1110 }
1111 RunCommandToFd(fd, "", {"cmd", "window", "dump-visible-window-views"},
Kevin Jeon774abde2022-09-28 18:20:43 +00001112 CommandOptions::WithTimeout(10).Build());
Sunny Goyal35949782019-11-19 15:54:36 -08001113 bool empty = 0 == lseek(fd, 0, SEEK_END);
1114 if (!empty) {
1115 ds.AddZipEntry("visible_windows.zip", path);
1116 } else {
1117 MYLOGW("Failed to dump visible windows\n");
1118 }
1119 unlink(path.c_str());
1120}
1121
Jayachandran Ca94c7172017-06-10 15:08:12 -07001122static void DumpIpTablesAsRoot() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001123 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
1124 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +09001125 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001126 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +09001127 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
1128 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
1129 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
1130 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001131}
1132
Woody Lin20767a92022-11-29 15:50:24 +08001133static void DumpShutdownCheckpoints() {
1134 const bool shutdown_checkpoints_dumped = AddDumps(
1135 ds.shutdown_checkpoints_.begin(), ds.shutdown_checkpoints_.end(),
1136 "SHUTDOWN CHECKPOINTS", false /* add_to_zip */);
1137 if (!shutdown_checkpoints_dumped) {
1138 printf("*** NO SHUTDOWN CHECKPOINTS to dump in %s\n\n",
1139 SHUTDOWN_CHECKPOINTS_DIR.c_str());
1140 }
1141}
1142
David Andersond9ba4752018-12-11 18:26:59 -08001143static void DumpDynamicPartitionInfo() {
1144 if (!::android::base::GetBoolProperty("ro.boot.dynamic_partitions", false)) {
1145 return;
1146 }
1147
1148 RunCommand("LPDUMP", {"lpdump", "--all"});
David Anderson6650ade2019-10-02 15:18:59 -07001149 RunCommand("DEVICE-MAPPER", {"gsid", "dump-device-mapper"});
David Andersond9ba4752018-12-11 18:26:59 -08001150}
1151
Chris Morin5a50d482022-02-01 17:41:18 -08001152static void AddAnrTraceDir(const std::string& anr_traces_dir) {
Narayan Kamath8f788292017-05-25 13:20:39 +01001153 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
1154 anr_traces_dir.c_str());
1155
1156 // If we're here, dump_traces_path will always be a temporary file
1157 // (created with mkostemp or similar) that contains dumps taken earlier
1158 // on in the process.
1159 if (dump_traces_path != nullptr) {
Chris Morin5a50d482022-02-01 17:41:18 -08001160 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
1161 dump_traces_path);
1162 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
Narayan Kamath8f788292017-05-25 13:20:39 +01001163
1164 const int ret = unlink(dump_traces_path);
1165 if (ret == -1) {
1166 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
1167 strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -07001168 }
1169 }
1170
Narayan Kamathbd863722017-06-01 18:50:12 +01001171 // Add a specific message for the first ANR Dump.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001172 if (ds.anr_data_.size() > 0) {
Chris Morin5a50d482022-02-01 17:41:18 -08001173 // The "last" ANR will always be present in the body of the main entry.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001174 AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1,
Chris Morin5a50d482022-02-01 17:41:18 -08001175 "VM TRACES AT LAST ANR", false /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001176
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001177 // Historical ANRs are always included as separate entries in the bugreport zip file.
Chris Morin5a50d482022-02-01 17:41:18 -08001178 AddDumps(ds.anr_data_.begin(), ds.anr_data_.end(),
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001179 "HISTORICAL ANR", true /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001180 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +01001181 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
1182 }
Andy Hungd62f7e62024-01-11 15:47:52 -08001183
1184 // Add Java anr traces (such as generated by the Finalizer Watchdog).
1185 AddDumps(ds.anr_trace_data_.begin(), ds.anr_trace_data_.end(), "JAVA ANR TRACES",
1186 true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001187}
1188
1189static void AddAnrTraceFiles() {
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001190 std::string anr_traces_dir = "/data/anr";
Narayan Kamath8f788292017-05-25 13:20:39 +01001191
Chris Morin5a50d482022-02-01 17:41:18 -08001192 AddAnrTraceDir(anr_traces_dir);
Narayan Kamath8f788292017-05-25 13:20:39 +01001193
Makoto Onuki83ec63f2019-01-31 17:08:59 -08001194 RunCommand("ANR FILES", {"ls", "-lt", ANR_DIR});
1195
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001196 // Slow traces for slow operations.
Felipe Lemee184f662016-10-27 10:04:47 -07001197 struct stat st;
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001198 int i = 0;
1199 while (true) {
1200 const std::string slow_trace_path =
1201 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
1202 if (stat(slow_trace_path.c_str(), &st)) {
1203 // No traces file at this index, done with the files.
1204 break;
Felipe Lemee184f662016-10-27 10:04:47 -07001205 }
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001206 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
1207 i++;
Felipe Lemee184f662016-10-27 10:04:47 -07001208 }
1209}
1210
Wei Wang509bb5d2017-06-09 14:42:12 -07001211static void DumpBlockStatFiles() {
1212 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -07001213
Wei Wang1dc1ef52017-06-12 11:28:37 -07001214 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
1215
1216 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001217 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1218 return;
1219 }
1220
1221 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -07001222 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001223 if ((d->d_name[0] == '.')
1224 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1225 || (d->d_name[1] == '\0'))) {
1226 continue;
1227 }
1228 const std::string new_path =
1229 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1230 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1231 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1232 printf("\n");
1233 }
Wei Wang1dc1ef52017-06-12 11:28:37 -07001234 return;
Wei Wang509bb5d2017-06-09 14:42:12 -07001235}
Jayachandran Ca94c7172017-06-10 15:08:12 -07001236
1237static void DumpPacketStats() {
1238 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
Jayachandran Ca94c7172017-06-10 15:08:12 -07001239}
1240
1241static void DumpIpAddrAndRules() {
1242 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
Ray Chencbf278a2023-11-20 07:49:45 +00001243 RunCommand("NETWORK INTERFACES", {"ip", "-s", "link"});
Jayachandran Ca94c7172017-06-10 15:08:12 -07001244 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1245 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1246 RunCommand("IP RULES", {"ip", "rule", "show"});
1247 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1248}
1249
Nandana Dutt5c390032019-03-12 10:52:56 +00001250static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, int priority,
1251 std::chrono::milliseconds timeout,
1252 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001253 auto start = std::chrono::steady_clock::now();
Vishnu Naire97d6122018-01-18 13:58:56 -08001254 sp<android::IServiceManager> sm = defaultServiceManager();
1255 Dumpsys dumpsys(sm.get());
Vishnu Naire97d6122018-01-18 13:58:56 -08001256 Vector<String16> args;
1257 Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
Vishnu Naire97d6122018-01-18 13:58:56 -08001258 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1259 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001260 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001261 std::string path(title);
1262 path.append(" - ").append(String8(service).c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -08001263 size_t bytes_written = 0;
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001264 if (PropertiesHelper::IsDryRun()) {
1265 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1266 dumpsys.writeDumpFooter(STDOUT_FILENO, service, std::chrono::milliseconds(1));
1267 } else {
Devin Mooref492c1a2023-03-15 19:19:03 +00001268 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP | Dumpsys::TYPE_PID |
1269 Dumpsys::TYPE_CLIENTS | Dumpsys::TYPE_THREAD,
Devin Mooreae68df22023-02-24 20:59:51 +00001270 service, args);
1271 if (status == OK) {
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001272 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1273 std::chrono::duration<double> elapsed_seconds;
1274 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH &&
1275 service == String16("meminfo")) {
1276 // Use a longer timeout for meminfo, since 30s is not always enough.
1277 status = dumpsys.writeDump(STDOUT_FILENO, service, 60s,
1278 /* as_proto = */ false, elapsed_seconds,
1279 bytes_written);
1280 } else {
1281 status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
1282 /* as_proto = */ false, elapsed_seconds,
1283 bytes_written);
1284 }
1285 dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
1286 bool dump_complete = (status == OK);
1287 dumpsys.stopDumpThread(dump_complete);
Devin Moorecdfa4602023-03-16 20:49:39 +00001288 } else {
1289 MYLOGE("Failed to start dump thread for service: %s, status: %d",
1290 String8(service).c_str(), status);
Gavin Corkeryfac7e2b2021-07-08 22:39:02 +01001291 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001292 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001293
1294 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1295 std::chrono::steady_clock::now() - start);
1296 if (elapsed_duration > timeout) {
1297 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1298 elapsed_duration.count());
1299 break;
1300 }
1301 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001302 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001303}
1304
Vishnu Nair64afc022018-02-01 15:29:34 -08001305static void RunDumpsysText(const std::string& title, int priority,
1306 std::chrono::milliseconds timeout,
1307 std::chrono::milliseconds service_timeout) {
1308 DurationReporter duration_reporter(title);
1309 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1310 fsync(STDOUT_FILENO);
1311 RunDumpsysTextByPriority(title, priority, timeout, service_timeout);
1312}
1313
1314/* Dump all services registered with Normal or Default priority. */
Nandana Dutt5c390032019-03-12 10:52:56 +00001315static Dumpstate::RunStatus RunDumpsysTextNormalPriority(const std::string& title,
1316 std::chrono::milliseconds timeout,
1317 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001318 DurationReporter duration_reporter(title);
1319 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1320 fsync(STDOUT_FILENO);
1321 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout,
1322 service_timeout);
Nandana Dutt5c390032019-03-12 10:52:56 +00001323
1324 RETURN_IF_USER_DENIED_CONSENT();
1325
1326 return RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1327 service_timeout);
Vishnu Nair64afc022018-02-01 15:29:34 -08001328}
1329
Nandana Dutt5c390032019-03-12 10:52:56 +00001330static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priority,
1331 std::chrono::milliseconds timeout,
1332 std::chrono::milliseconds service_timeout) {
Vishnu Naire97d6122018-01-18 13:58:56 -08001333 sp<android::IServiceManager> sm = defaultServiceManager();
1334 Dumpsys dumpsys(sm.get());
1335 Vector<String16> args;
1336 Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
1337 DurationReporter duration_reporter(title);
1338
1339 auto start = std::chrono::steady_clock::now();
1340 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
1341 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001342 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001343 std::string path(kProtoPath);
1344 path.append(String8(service).c_str());
1345 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
1346 path.append("_CRITICAL");
1347 } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
1348 path.append("_HIGH");
1349 }
1350 path.append(kProtoExt);
Steven Morelandcbd69fc2021-07-20 20:45:43 +00001351 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP, service, args);
Vishnu Naire97d6122018-01-18 13:58:56 -08001352 if (status == OK) {
1353 status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
1354 bool dumpTerminated = (status == OK);
1355 dumpsys.stopDumpThread(dumpTerminated);
1356 }
1357 ZipWriter::FileEntry file_entry;
1358 ds.zip_writer_->GetLastEntry(&file_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -08001359
1360 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1361 std::chrono::steady_clock::now() - start);
1362 if (elapsed_duration > timeout) {
1363 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1364 elapsed_duration.count());
1365 break;
1366 }
1367 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001368 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001369}
1370
Nandana Dutta7db6342018-11-21 14:53:34 +00001371// Runs dumpsys on services that must dump first and will take less than 100ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001372static Dumpstate::RunStatus RunDumpsysCritical() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001373 RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1374 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Nandana Dutt5c390032019-03-12 10:52:56 +00001375
1376 RETURN_IF_USER_DENIED_CONSENT();
1377
1378 return RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1379 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Vishnu Nair780b1282017-10-10 13:57:24 -07001380}
1381
1382// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001383static Dumpstate::RunStatus RunDumpsysHigh() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001384 // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
1385 // high priority. Reduce timeout once they are able to dump in a shorter time or
1386 // moved to a parallel task.
1387 RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1388 /* timeout= */ 90s, /* service_timeout= */ 30s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001389
1390 RETURN_IF_USER_DENIED_CONSENT();
1391
1392 return RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1393 /* timeout= */ 5s, /* service_timeout= */ 1s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001394}
1395
1396// Runs dumpsys on services that must dump but can take up to 10s to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001397static Dumpstate::RunStatus RunDumpsysNormal() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001398 RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001399
1400 RETURN_IF_USER_DENIED_CONSENT();
1401
1402 return RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1403 /* timeout= */ 90s, /* service_timeout= */ 10s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001404}
1405
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001406/*
1407 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1408 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1409 * if it's not running in the parallel task.
1410 */
1411static void DumpHals(int out_fd = STDOUT_FILENO) {
Yifan Hong30528a22020-08-07 18:24:06 -07001412 RunCommand("HARDWARE HALS", {"lshal", "--all", "--types=all"},
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001413 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build(),
1414 false, out_fd);
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001415
Steven Moreland44cd9482018-01-04 16:24:13 -08001416 using android::hidl::manager::V1_0::IServiceManager;
1417 using android::hardware::defaultServiceManager;
1418
1419 sp<IServiceManager> sm = defaultServiceManager();
1420 if (sm == nullptr) {
1421 MYLOGE("Could not retrieve hwservicemanager to dump hals.\n");
1422 return;
1423 }
1424
1425 auto ret = sm->list([&](const auto& interfaces) {
1426 for (const std::string& interface : interfaces) {
1427 std::string cleanName = interface;
Steven Morelandc6b1fc22023-07-26 23:53:58 +00001428 std::replace_if(
1429 cleanName.begin(), cleanName.end(),
1430 [](char c) {
1431 return !isalnum(c) && std::string("@-_.").find(c) == std::string::npos;
1432 },
1433 '_');
Nandana Dutt979388e2018-11-30 16:48:55 +00001434 const std::string path = ds.bugreport_internal_dir_ + "/lshal_debug_" + cleanName;
Steven Moreland44cd9482018-01-04 16:24:13 -08001435
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001436 bool empty = false;
Steven Moreland44cd9482018-01-04 16:24:13 -08001437 {
1438 auto fd = android::base::unique_fd(
1439 TEMP_FAILURE_RETRY(open(path.c_str(),
1440 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1441 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1442 if (fd < 0) {
1443 MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str());
1444 continue;
1445 }
1446 RunCommandToFd(fd,
1447 "",
Steven Morelandc81cd3c2018-01-18 14:36:26 -08001448 {"lshal", "debug", "-E", interface},
Steven Moreland44cd9482018-01-04 16:24:13 -08001449 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1450
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001451 empty = 0 == lseek(fd, 0, SEEK_END);
Steven Moreland44cd9482018-01-04 16:24:13 -08001452 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001453 if (!empty) {
1454 ds.EnqueueAddZipEntryAndCleanupIfNeeded("lshal-debug/" + cleanName + ".txt",
1455 path);
1456 } else {
1457 unlink(path.c_str());
1458 }
Steven Moreland44cd9482018-01-04 16:24:13 -08001459 }
1460 });
1461
1462 if (!ret.isOk()) {
1463 MYLOGE("Could not list hals from hwservicemanager.\n");
1464 }
1465}
1466
Devin Moore8df81bb2022-06-08 22:47:02 +00001467// Dump all of the files that make up the vendor interface.
1468// See the files listed in dumpFileList() for the latest list of files.
1469static void DumpVintf() {
Devin Moore16271d92022-09-22 18:28:48 +00001470
1471 const std::string sku = android::base::GetProperty("ro.boot.product.hardware.sku", "");
1472 const auto vintfFiles = android::vintf::details::dumpFileList(sku);
Devin Moore8df81bb2022-06-08 22:47:02 +00001473 for (const auto vintfFile : vintfFiles) {
1474 struct stat st;
1475 if (stat(vintfFile.c_str(), &st) == 0) {
1476 if (S_ISDIR(st.st_mode)) {
1477 ds.AddDir(vintfFile, true /* recursive */);
1478 } else {
1479 ds.EnqueueAddZipEntryAndCleanupIfNeeded(ZIP_ROOT_DIR + vintfFile,
1480 vintfFile);
1481 }
1482 }
1483 }
1484}
1485
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001486static void DumpExternalFragmentationInfo() {
1487 struct stat st;
1488 if (stat("/proc/buddyinfo", &st) != 0) {
1489 MYLOGE("Unable to dump external fragmentation info\n");
1490 return;
1491 }
1492
1493 printf("------ EXTERNAL FRAGMENTATION INFO ------\n");
1494 std::ifstream ifs("/proc/buddyinfo");
1495 auto unusable_index_regex = std::regex{"Node\\s+([0-9]+),\\s+zone\\s+(\\S+)\\s+(.*)"};
1496 for (std::string line; std::getline(ifs, line);) {
1497 std::smatch match_results;
1498 if (std::regex_match(line, match_results, unusable_index_regex)) {
1499 std::stringstream free_pages(std::string{match_results[3]});
1500 std::vector<int> free_pages_per_order(std::istream_iterator<int>{free_pages},
1501 std::istream_iterator<int>());
1502
1503 int total_free_pages = 0;
1504 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1505 total_free_pages += (free_pages_per_order[i] * std::pow(2, i));
1506 }
1507
1508 printf("Node %s, zone %8s", match_results[1].str().c_str(),
1509 match_results[2].str().c_str());
1510
1511 int usable_free_pages = total_free_pages;
1512 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1513 auto unusable_index = (total_free_pages - usable_free_pages) /
1514 static_cast<double>(total_free_pages);
1515 printf(" %5.3f", unusable_index);
1516 usable_free_pages -= (free_pages_per_order[i] * std::pow(2, i));
1517 }
1518
1519 printf("\n");
1520 }
1521 }
1522 printf("\n");
1523}
1524
mhasankd451a472020-05-26 18:02:39 -07001525static void DumpstateLimitedOnly() {
EdenSue8fe4522023-11-20 15:37:23 +08001526 // Trimmed-down version of dumpstate to only include a allowlisted
mhasankd451a472020-05-26 18:02:39 -07001527 // set of logs (system log, event log, and system server / system app
1528 // crashes, and networking logs). See b/136273873 and b/138459828
1529 // for context.
1530 DurationReporter duration_reporter("DUMPSTATE");
1531 unsigned long timeout_ms;
1532 // calculate timeout
1533 timeout_ms = logcat_timeout({"main", "system", "crash"});
1534 RunCommand("SYSTEM LOG",
1535 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1536 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1537 timeout_ms = logcat_timeout({"events"});
1538 RunCommand(
1539 "EVENT LOG",
1540 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1541 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1542
1543 printf("========================================================\n");
1544 printf("== Networking Service\n");
1545 printf("========================================================\n");
1546
1547 RunDumpsys("DUMPSYS NETWORK_SERVICE_LIMITED", {"wifi", "-a"},
1548 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hugo Benichiaa162682020-10-30 23:28:56 +09001549 RunDumpsys("DUMPSYS CONNECTIVITY REQUESTS", {"connectivity", "requests"},
1550 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
mhasankd451a472020-05-26 18:02:39 -07001551
1552 printf("========================================================\n");
1553 printf("== Dropbox crashes\n");
1554 printf("========================================================\n");
1555
1556 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1557 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1558
1559 printf("========================================================\n");
1560 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1561 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1562 printf("========================================================\n");
1563 printf("== dumpstate: done (id %d)\n", ds.id_);
1564 printf("========================================================\n");
1565}
1566
Rhed Jaoe017f982020-07-21 17:58:41 +08001567/*
1568 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1569 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1570 * if it's not running in the parallel task.
1571 */
1572static void DumpCheckins(int out_fd = STDOUT_FILENO) {
1573 dprintf(out_fd, "========================================================\n");
1574 dprintf(out_fd, "== Checkins\n");
1575 dprintf(out_fd, "========================================================\n");
1576
1577 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"}, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001578 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"}, out_fd);
1579 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"}, out_fd);
1580 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"}, out_fd);
1581 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"}, out_fd);
1582}
1583
1584/*
1585 * Runs dumpsys on activity service to dump all application activities, services
1586 * and providers in the device.
1587 *
1588 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1589 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1590 * if it's not running in the parallel task.
1591 */
1592static void DumpAppInfos(int out_fd = STDOUT_FILENO) {
1593 dprintf(out_fd, "========================================================\n");
1594 dprintf(out_fd, "== Running Application Activities\n");
1595 dprintf(out_fd, "========================================================\n");
1596
1597 // The following dumpsys internally collects output from running apps, so it can take a long
1598 // time. So let's extend the timeout.
1599
1600 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1601
1602 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1603
1604 dprintf(out_fd, "========================================================\n");
1605 dprintf(out_fd, "== Running Application Services (platform)\n");
1606 dprintf(out_fd, "========================================================\n");
1607
1608 RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
1609 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1610
1611 dprintf(out_fd, "========================================================\n");
1612 dprintf(out_fd, "== Running Application Services (non-platform)\n");
1613 dprintf(out_fd, "========================================================\n");
1614
1615 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1616 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1617
1618 dprintf(out_fd, "========================================================\n");
1619 dprintf(out_fd, "== Running Application Providers (platform)\n");
1620 dprintf(out_fd, "========================================================\n");
1621
1622 RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
Rhed Jaob049f182021-01-11 21:08:43 +08001623 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001624
1625 dprintf(out_fd, "========================================================\n");
1626 dprintf(out_fd, "== Running Application Providers (non-platform)\n");
1627 dprintf(out_fd, "========================================================\n");
1628
1629 RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1630 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1631}
1632
Nandana Dutt5c390032019-03-12 10:52:56 +00001633// Dumps various things. Returns early with status USER_CONSENT_DENIED if user denies consent
1634// via the consent they are shown. Ignores other errors that occur while running various
1635// commands. The consent checking is currently done around long running tasks, which happen to
1636// be distributed fairly evenly throughout the function.
Kean Mariotti306633e2022-09-05 16:30:47 +00001637Dumpstate::RunStatus Dumpstate::dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001638 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001639
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001640 // Enqueue slow functions into the thread pool, if the parallel run is enabled.
Aaron Huanga99452a2022-04-27 18:51:16 +08001641 std::future<std::string> dump_hals, dump_incident_report, dump_board, dump_checkins,
Kean Mariotti306633e2022-09-05 16:30:47 +00001642 dump_netstats_report, post_process_ui_traces;
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001643 if (ds.dump_pool_) {
1644 // Pool was shutdown in DumpstateDefaultAfterCritical method in order to
Kean Mariotti306633e2022-09-05 16:30:47 +00001645 // drop root user. Restarts it.
1646 ds.dump_pool_->start(/* thread_counts = */3);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001647
Chris Morinbc223142022-02-04 14:17:11 -08001648 dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
1649 dump_incident_report = ds.dump_pool_->enqueueTask(
1650 DUMP_INCIDENT_REPORT_TASK, &DumpIncidentReport);
Aaron Huanga99452a2022-04-27 18:51:16 +08001651 dump_netstats_report = ds.dump_pool_->enqueueTask(
1652 DUMP_NETSTATS_PROTO_TASK, &DumpNetstatsProto);
Chris Morinbc223142022-02-04 14:17:11 -08001653 dump_board = ds.dump_pool_->enqueueTaskWithFd(
1654 DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
1655 dump_checkins = ds.dump_pool_->enqueueTaskWithFd(DUMP_CHECKINS_TASK, &DumpCheckins, _1);
Kean Mariotti306633e2022-09-05 16:30:47 +00001656 post_process_ui_traces = ds.dump_pool_->enqueueTask(
1657 POST_PROCESS_UI_TRACES_TASK, &Dumpstate::MaybePostProcessUiTraces, &ds);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001658 }
1659
Nandana Dutt5c390032019-03-12 10:52:56 +00001660 // Dump various things. Note that anything that takes "long" (i.e. several seconds) should
1661 // check intermittently (if it's intrerruptable like a foreach on pids) and/or should be wrapped
1662 // in a consent check (via RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK).
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001663 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001664 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001665 DumpBlockStatFiles();
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001666 DumpFile("MEMORY INFO", "/proc/meminfo");
1667 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001668 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001669
Kevin Jeon947922b2022-09-21 00:29:18 +00001670 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "BUGREPORT_PROCDUMP", {"bugreport_procdump"},
1671 CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001672
Sunny Goyal35949782019-11-19 15:54:36 -08001673 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpVisibleWindowViews);
1674
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001675 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1676 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1677 DumpFile("SLAB INFO", "/proc/slabinfo");
1678 DumpFile("ZONEINFO", "/proc/zoneinfo");
1679 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1680 DumpFile("BUDDYINFO", "/proc/buddyinfo");
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001681 DumpExternalFragmentationInfo();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001682
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001683 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001684
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001685 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001686 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001687
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001688 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001689 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_hals));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001690 } else {
1691 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_HALS_TASK, DumpHals);
1692 }
Steven Moreland81b429e2017-01-31 19:50:46 -08001693
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001694 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001695 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001696 struct stat s;
1697 if (stat("/proc/modules", &s) != 0) {
1698 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1699 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001700 RunCommand("LSMOD", {"lsmod"});
Woody Linc198f252021-05-04 16:37:11 +08001701 RunCommand("MODULES INFO",
1702 {"sh", "-c", "cat /proc/modules | cut -d' ' -f1 | "
1703 " while read MOD ; do echo modinfo:$MOD ; modinfo $MOD ; "
1704 "done"}, CommandOptions::AS_ROOT);
Felipe Lemee4eca582016-06-10 17:48:08 -07001705 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001706
Tom Cherryb87dbfa2020-07-28 11:28:53 -07001707 if (android::base::GetBoolProperty("ro.logd.kernel", false)) {
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001708 DoKernelLogcat();
1709 } else {
1710 do_dmesg();
1711 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001712
Devin Moore8df81bb2022-06-08 22:47:02 +00001713 DumpVintf();
1714
Felipe Lemef0292972016-11-22 13:57:05 -08001715 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001716
Jeff Brown1dc94e32014-09-11 14:15:27 -07001717 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001718 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001719
Jack Yu5a6b2e22020-08-14 18:13:35 +08001720 /* Dump Nfc NCI logs */
1721 ds.AddDir("/data/misc/nfc/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001722
Paul Chang0d2aad72020-02-13 20:04:03 +08001723 if (ds.options_->do_screenshot && !ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001724 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001725 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001726 }
1727
Felipe Lemee184f662016-10-27 10:04:47 -07001728 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001729
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001730 MaybeAddSystemTraceToZip();
1731
Narayan Kamath8f788292017-05-25 13:20:39 +01001732 // NOTE: tombstones are always added as separate entries in the zip archive
1733 // and are not interspersed with the main report.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001734 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
Narayan Kamathbd863722017-06-01 18:50:12 +01001735 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001736 if (!tombstones_dumped) {
1737 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001738 }
1739
Jayachandran Ca94c7172017-06-10 15:08:12 -07001740 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001741
Lorenzo Colitti807f2dd2022-05-27 12:48:37 +09001742 RunDumpsys("EBPF MAP STATS", {"connectivity", "trafficcontroller"});
Chenbo Feng276a3b62018-08-07 11:44:49 -07001743
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001744 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001745
Woody Lin20767a92022-11-29 15:50:24 +08001746 DumpShutdownCheckpoints();
1747
Jayachandran Ca94c7172017-06-10 15:08:12 -07001748 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001749
1750 dump_route_tables();
1751
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001752 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1753 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1754 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001755
Nandana Dutt5c390032019-03-12 10:52:56 +00001756 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysHigh);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001757
Chiachang Wang668ede42021-05-17 17:14:20 +08001758 // The dump mechanism in connectivity is refactored due to modularization work. Connectivity can
1759 // only register with a default priority(NORMAL priority). Dumpstate has to call connectivity
1760 // dump with priority parameters to dump high priority information.
1761 RunDumpsys("SERVICE HIGH connectivity", {"connectivity", "--dump-priority", "HIGH"},
1762 CommandOptions::WithTimeout(10).Build());
1763
Elliott Hughes23ccc622017-02-28 10:14:22 -08001764 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001765
Joe Onoratod38bc3a2023-06-29 15:48:28 -07001766 DumpFile("SYSTEM BUILD-TIME RELEASE FLAGS", "/system/etc/build_flags.json");
1767 DumpFile("SYSTEM_EXT BUILD-TIME RELEASE FLAGS", "/system_ext/etc/build_flags.json");
1768 DumpFile("PRODUCT BUILD-TIME RELEASE FLAGS", "/product/etc/build_flags.json");
1769 DumpFile("VENDOR BUILD-TIME RELEASE FLAGS", "/vendor/etc/build_flags.json");
1770
Mårten Kongstad5ad813f2023-09-28 10:09:18 +02001771 RunCommand("ACONFIG FLAGS", {PRINT_FLAGS},
1772 CommandOptions::WithTimeout(10).Always().DropRoot().Build());
Joe Onoratod38bc3a2023-06-29 15:48:28 -07001773
Jin Qianf334d662017-10-10 14:41:37 -07001774 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001775
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001776 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001777
Colin Crossf45fa6b2012-03-26 12:38:26 -07001778 /* Binder state is expensive to look at as it uses a lot of memory. */
Hridya Valsaraju920ba712020-02-09 16:27:01 -08001779 std::string binder_logs_dir = access("/dev/binderfs/binder_logs", R_OK) ?
1780 "/sys/kernel/debug/binder" : "/dev/binderfs/binder_logs";
1781
1782 DumpFile("BINDER FAILED TRANSACTION LOG", binder_logs_dir + "/failed_transaction_log");
1783 DumpFile("BINDER TRANSACTION LOG", binder_logs_dir + "/transaction_log");
1784 DumpFile("BINDER TRANSACTIONS", binder_logs_dir + "/transactions");
1785 DumpFile("BINDER STATS", binder_logs_dir + "/stats");
1786 DumpFile("BINDER STATE", binder_logs_dir + "/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001787
Yifan Hongd90cc652020-02-08 16:52:02 -08001788 ds.AddDir(SNAPSHOTCTL_LOG_DIR, false);
1789
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001790 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001791 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_board));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001792 } else {
1793 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
1794 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001795
Steven Moreland7440ddb2016-12-15 16:13:39 -08001796 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001797 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1798 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001799 // su does not exist on user builds, so try running without it.
1800 // This way any implementations of vril-dump that do not require
1801 // root can run on user builds.
1802 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001803 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001804 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001805 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001806 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001807 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001808 }
1809
Felipe Lemed8b94e52016-12-08 10:21:44 -08001810 printf("========================================================\n");
1811 printf("== Android Framework Services\n");
1812 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001813
Nandana Dutt5c390032019-03-12 10:52:56 +00001814 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001815
Jack He91ff2fe2021-02-18 18:23:43 -08001816 /* Dump Bluetooth HCI logs after getting bluetooth_manager dumpsys */
1817 ds.AddDir("/data/misc/bluetooth/logs", true);
1818
Rhed Jaoe017f982020-07-21 17:58:41 +08001819 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001820 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_checkins));
Rhed Jaoe017f982020-07-21 17:58:41 +08001821 } else {
1822 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_CHECKINS_TASK, DumpCheckins);
1823 }
Dianne Hackborn02bea972013-06-26 18:59:09 -07001824
Rhed Jaoc5f7ec32020-12-22 22:11:08 +08001825 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpAppInfos);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001826
Adrian Roos8b397ab2017-04-04 16:35:44 -07001827 printf("========================================================\n");
1828 printf("== Dropbox crashes\n");
1829 printf("========================================================\n");
1830
1831 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1832 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1833
Felipe Lemed8b94e52016-12-08 10:21:44 -08001834 printf("========================================================\n");
1835 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1836 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1837 printf("========================================================\n");
1838 printf("== dumpstate: done (id %d)\n", ds.id_);
1839 printf("========================================================\n");
Bookatz38472142018-09-28 10:20:24 -07001840
1841 printf("========================================================\n");
1842 printf("== Obtaining statsd metadata\n");
1843 printf("========================================================\n");
1844 // This differs from the usual dumpsys stats, which is the stats report data.
1845 RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
Mike Ma5c267872019-08-21 11:31:34 -07001846
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +09001847 // Add linker configuration directory
1848 ds.AddDir(LINKERCONFIG_DIR, true);
1849
Li Li830179f2022-01-04 12:53:29 -08001850 /* Dump frozen cgroupfs */
1851 dump_frozen_cgroupfs();
Li Li2eedd412021-06-30 15:11:53 -07001852
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001853 if (ds.dump_pool_) {
Aaron Huanga99452a2022-04-27 18:51:16 +08001854 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_netstats_report));
1855 } else {
1856 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_NETSTATS_PROTO_TASK,
1857 DumpNetstatsProto);
1858 }
1859
1860 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001861 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_incident_report));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001862 } else {
1863 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_INCIDENT_REPORT_TASK,
1864 DumpIncidentReport);
1865 }
Mike Ma5c267872019-08-21 11:31:34 -07001866
Kean Mariotti306633e2022-09-05 16:30:47 +00001867 if (ds.dump_pool_) {
1868 WaitForTask(std::move(post_process_ui_traces));
1869 } else {
1870 RUN_SLOW_FUNCTION_AND_LOG(POST_PROCESS_UI_TRACES_TASK, MaybePostProcessUiTraces);
1871 }
1872
1873 MaybeAddUiTracesToZip();
1874
Nandana Dutt5c390032019-03-12 10:52:56 +00001875 return Dumpstate::RunStatus::OK;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001876}
1877
Nandana Dutt5c390032019-03-12 10:52:56 +00001878/*
1879 * Dumps state for the default case; drops root after it's no longer necessary.
1880 *
1881 * Returns RunStatus::OK if everything went fine.
1882 * Returns RunStatus::ERROR if there was an error.
1883 * Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport
1884 * with the caller.
1885 */
Jichao Lie89d9c12019-11-21 19:02:51 -08001886Dumpstate::RunStatus Dumpstate::DumpstateDefaultAfterCritical() {
Nandana Duttdb379fa2019-10-09 16:54:41 +01001887 // Capture first logcat early on; useful to take a snapshot before dumpstate logs take over the
1888 // buffer.
1889 DoLogcat();
1890 // Capture timestamp after first logcat to use in next logcat
1891 time_t logcat_ts = time(nullptr);
1892
Nandana Dutt4be45d12018-09-26 15:04:23 +01001893 /* collect stack traces from Dalvik and native processes (needs root) */
Chris Morinbc223142022-02-04 14:17:11 -08001894 std::future<std::string> dump_traces;
Rhed Jao5377d792020-07-16 17:37:39 +08001895 if (dump_pool_) {
1896 RETURN_IF_USER_DENIED_CONSENT();
1897 // One thread is enough since we only need to enqueue DumpTraces here.
1898 dump_pool_->start(/* thread_counts = */1);
1899
1900 // DumpTraces takes long time, post it to the another thread in the
1901 // pool, if pool is available
Chris Morinbc223142022-02-04 14:17:11 -08001902 dump_traces = dump_pool_->enqueueTask(
1903 DUMP_TRACES_TASK, &Dumpstate::DumpTraces, &ds, &dump_traces_path);
Rhed Jao5377d792020-07-16 17:37:39 +08001904 } else {
1905 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_TRACES_TASK, ds.DumpTraces,
1906 &dump_traces_path);
1907 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001908
1909 /* Run some operations that require root. */
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001910 if (!PropertiesHelper::IsDryRun()) {
Chris Morinc2cba7a2022-02-01 17:06:50 -08001911 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX);
1912 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX);
Andy Hungd62f7e62024-01-11 15:47:52 -08001913 ds.anr_trace_data_ = GetDumpFds(ANR_DIR, ANR_TRACE_FILE_PREFIX);
Woody Lin20767a92022-11-29 15:50:24 +08001914 ds.shutdown_checkpoints_ = GetDumpFds(
1915 SHUTDOWN_CHECKPOINTS_DIR, SHUTDOWN_CHECKPOINTS_FILE_PREFIX);
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001916 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001917
1918 ds.AddDir(RECOVERY_DIR, true);
1919 ds.AddDir(RECOVERY_DATA_DIR, true);
1920 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
Kelvin Zhang6eaa0f92022-09-12 09:29:19 -07001921 ds.AddDir(UPDATE_ENGINE_PREF_DIR, true);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001922 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1923 if (!PropertiesHelper::IsUserBuild()) {
1924 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1925 ds.AddDir(PROFILE_DATA_DIR_REF, true);
Calin Juravlef84d3692020-04-28 15:31:12 -07001926 ds.AddZipEntry(ZIP_ROOT_DIR + PACKAGE_DEX_USE_LIST, PACKAGE_DEX_USE_LIST);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001927 }
Jerry Changa1df8a92020-01-02 16:03:39 +08001928 ds.AddDir(PREREBOOT_DATA_DIR, false);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001929 add_mountinfo();
Peter Collingbourne78aa2942023-02-15 14:50:31 -08001930 for (const char* path : {"/proc/cpuinfo", "/proc/meminfo"}) {
1931 ds.AddZipEntry(ZIP_ROOT_DIR + path, path);
1932 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001933 DumpIpTablesAsRoot();
David Andersond9ba4752018-12-11 18:26:59 -08001934 DumpDynamicPartitionInfo();
Yifan Hong3945e1b2019-10-29 12:59:23 -07001935 ds.AddDir(OTA_METADATA_DIR, true);
Jeff Sharkey9df29d52023-02-06 14:26:30 -07001936 if (!PropertiesHelper::IsUserBuild()) {
1937 // Include dropbox entry files inside ZIP, but exclude
1938 // noisy WTF and StrictMode entries
1939 dump_files("", DROPBOX_DIR, skip_wtf_strictmode, _add_file_from_fd);
1940 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001941
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001942 // Capture any IPSec policies in play. No keys are exposed here.
Nandana Dutt4be45d12018-09-26 15:04:23 +01001943 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1944
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001945 // Dump IPsec stats. No keys are exposed here.
1946 DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
1947
Nandana Dutt4be45d12018-09-26 15:04:23 +01001948 // Run ss as root so we can see socket marks.
1949 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1950
1951 // Run iotop as root to show top 100 IO threads
1952 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1953
Erick Reyese68df822019-02-11 14:46:36 -08001954 // Gather shared memory buffer info if the product implements it
Hridya Valsaraju1da80c52021-01-09 22:10:11 -08001955 RunCommand("Dmabuf dump", {"dmabuf_dump"});
1956 RunCommand("Dmabuf per-buffer/per-exporter/per-device stats", {"dmabuf_dump", "-b"});
Erick Reyese68df822019-02-11 14:46:36 -08001957
Minchan Kim22c6a1e2019-09-30 15:58:10 -07001958 DumpFile("PSI cpu", "/proc/pressure/cpu");
1959 DumpFile("PSI memory", "/proc/pressure/memory");
1960 DumpFile("PSI io", "/proc/pressure/io");
1961
Steven Moreland9379c462023-12-21 02:04:27 +00001962 ds.AddZipEntry(ZIP_ROOT_DIR + KERNEL_CONFIG, KERNEL_CONFIG);
1963
Mårten Kongstad60195a72022-09-20 14:14:20 +02001964 RunCommand("SDK EXTENSIONS", {SDK_EXT_INFO, "--dump"},
1965 CommandOptions::WithTimeout(10).Always().DropRoot().Build());
1966
Rhed Jao5377d792020-07-16 17:37:39 +08001967 if (dump_pool_) {
1968 RETURN_IF_USER_DENIED_CONSENT();
Chris Morinbc223142022-02-04 14:17:11 -08001969 WaitForTask(std::move(dump_traces));
Rhed Jao5377d792020-07-16 17:37:39 +08001970
Chris Morinbc223142022-02-04 14:17:11 -08001971 // Current running thread in the pool is the root user also. Delete
1972 // the pool and make a new one later to ensure none of threads in the pool are root.
1973 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao5377d792020-07-16 17:37:39 +08001974 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001975 if (!DropRootUser()) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001976 return Dumpstate::RunStatus::ERROR;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001977 }
1978
Nandana Dutt5c390032019-03-12 10:52:56 +00001979 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttdb379fa2019-10-09 16:54:41 +01001980 Dumpstate::RunStatus status = dumpstate();
1981 // Capture logcat since the last time we did it.
1982 DoSystemLogcat(logcat_ts);
1983 return status;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001984}
1985
Rhed Jaob5685b32020-08-14 17:19:17 +08001986// Common states for telephony and wifi which are needed to be collected before
1987// dumpstate drop the root user.
1988static void DumpstateRadioAsRoot() {
1989 DumpIpTablesAsRoot();
1990 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1991}
1992
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001993// This method collects common dumpsys for telephony and wifi. Typically, wifi
1994// reports are fine to include all information, but telephony reports on user
1995// builds need to strip some content (see DumpstateTelephonyOnly).
1996static void DumpstateRadioCommon(bool include_sensitive_info = true) {
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001997 // We need to be picky about some stuff for telephony reports on user builds.
1998 if (!include_sensitive_info) {
1999 // Only dump the radio log buffer (other buffers and dumps contain too much unrelated info).
2000 DoRadioLogcat();
2001 } else {
Rhed Jaob5685b32020-08-14 17:19:17 +08002002 // DumpHals takes long time, post it to the another thread in the pool,
2003 // if pool is available.
Chris Morinbc223142022-02-04 14:17:11 -08002004 std::future<std::string> dump_hals;
Rhed Jaob5685b32020-08-14 17:19:17 +08002005 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002006 dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
Rhed Jaob5685b32020-08-14 17:19:17 +08002007 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002008 // Contains various system properties and process startup info.
2009 do_dmesg();
2010 // Logs other than the radio buffer may contain package/component names and potential PII.
2011 DoLogcat();
2012 // Too broad for connectivity problems.
2013 DoKmsg();
Rhed Jaob5685b32020-08-14 17:19:17 +08002014 // DumpHals contains unrelated hardware info (camera, NFC, biometrics, ...).
2015 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002016 WaitForTask(std::move(dump_hals));
Rhed Jaob5685b32020-08-14 17:19:17 +08002017 } else {
2018 RUN_SLOW_FUNCTION_AND_LOG(DUMP_HALS_TASK, DumpHals);
2019 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002020 }
2021
Jayachandran Ca94c7172017-06-10 15:08:12 -07002022 DumpPacketStats();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002023 DumpIpAddrAndRules();
2024 dump_route_tables();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002025 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
2026 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08002027}
2028
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002029// We use "telephony" here for legacy reasons, though this now really means "connectivity" (cellular
2030// + wifi + networking). This method collects dumpsys for connectivity debugging only. General rules
2031// for what can be included on user builds: all reported information MUST directly relate to
2032// connectivity debugging or customer support and MUST NOT contain unrelated personally identifiable
2033// information. This information MUST NOT identify user-installed packages (UIDs are OK, package
2034// names are not), and MUST NOT contain logs of user application traffic.
2035// TODO(b/148168577) rename this and other related fields/methods to "connectivity" instead.
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08002036static void DumpstateTelephonyOnly(const std::string& calling_package) {
mukesh agrawal253dad42018-01-23 21:59:59 -08002037 DurationReporter duration_reporter("DUMPSTATE");
Jichao Lie89d9c12019-11-21 19:02:51 -08002038
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002039 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
mukesh agrawal253dad42018-01-23 21:59:59 -08002040
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002041 const bool include_sensitive_info = !PropertiesHelper::IsUserBuild();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002042
Rhed Jaob5685b32020-08-14 17:19:17 +08002043 DumpstateRadioAsRoot();
2044 if (!DropRootUser()) {
2045 return;
2046 }
2047
2048 // Starts thread pool after the root user is dropped, and two additional threads
2049 // are created for DumpHals in the DumpstateRadioCommon and DumpstateBoard.
Chris Morinbc223142022-02-04 14:17:11 -08002050 std::future<std::string> dump_board;
Rhed Jaob5685b32020-08-14 17:19:17 +08002051 if (ds.dump_pool_) {
2052 ds.dump_pool_->start(/*thread_counts =*/2);
2053
2054 // DumpstateBoard takes long time, post it to the another thread in the pool,
2055 // if pool is available.
Chris Morinbc223142022-02-04 14:17:11 -08002056 dump_board = ds.dump_pool_->enqueueTaskWithFd(
2057 DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
Rhed Jaob5685b32020-08-14 17:19:17 +08002058 }
2059
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002060 DumpstateRadioCommon(include_sensitive_info);
2061
2062 if (include_sensitive_info) {
2063 // Contains too much unrelated PII, and given the unstructured nature of sysprops, we can't
2064 // really cherrypick all of the connectivity-related ones. Apps generally have no business
2065 // reading these anyway, and there should be APIs to supply the info in a more app-friendly
2066 // way.
2067 RunCommand("SYSTEM PROPERTIES", {"getprop"});
2068 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002069
2070 printf("========================================================\n");
2071 printf("== Android Framework Services\n");
2072 printf("========================================================\n");
2073
Vishnu Nair652cc802017-11-30 15:18:30 -08002074 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2075 SEC_TO_MSEC(10));
Hunter Knepshield31cbae12021-05-11 16:23:24 -07002076 RunDumpsys("DUMPSYS", {"vcn_management"}, CommandOptions::WithTimeout(90).Build(),
2077 SEC_TO_MSEC(10));
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08002078 if (include_sensitive_info) {
2079 // Carrier apps' services will be dumped below in dumpsys activity service all-non-platform.
2080 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
2081 SEC_TO_MSEC(10));
2082 } else {
2083 // If the caller is a carrier app and has a carrier service, dump it here since we aren't
2084 // running dumpsys activity service all-non-platform below. Due to the increased output, we
2085 // give a higher timeout as well.
2086 RunDumpsys("DUMPSYS", {"carrier_config", "--requesting-package", calling_package},
2087 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(30));
2088 }
2089 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002090 RunDumpsys("DUMPSYS", {"netpolicy"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2091 RunDumpsys("DUMPSYS", {"network_management"}, CommandOptions::WithTimeout(90).Build(),
Sooraj Sasindrane8d98912018-04-20 11:31:55 -07002092 SEC_TO_MSEC(10));
Hunter Knepshield0fe51b12020-03-05 16:58:20 -08002093 RunDumpsys("DUMPSYS", {"telephony.registry"}, CommandOptions::WithTimeout(90).Build(),
2094 SEC_TO_MSEC(10));
Jack Yu773cc032023-03-16 22:43:39 -07002095 RunDumpsys("DUMPSYS", {"isub"}, CommandOptions::WithTimeout(90).Build(),
2096 SEC_TO_MSEC(10));
Grant Menke9bf3b2b2023-02-24 13:11:07 -08002097 RunDumpsys("DUMPSYS", {"telecom"}, CommandOptions::WithTimeout(90).Build(),
2098 SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002099 if (include_sensitive_info) {
2100 // Contains raw IP addresses, omit from reports on user builds.
2101 RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2102 // Contains raw destination IP/MAC addresses, omit from reports on user builds.
2103 RunDumpsys("DUMPSYS", {"connmetrics"}, CommandOptions::WithTimeout(90).Build(),
2104 SEC_TO_MSEC(10));
2105 // Contains package/component names, omit from reports on user builds.
2106 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
2107 SEC_TO_MSEC(10));
2108 // Contains package names, but should be relatively simple to remove them (also contains
2109 // UIDs already), omit from reports on user builds.
2110 RunDumpsys("BATTERYSTATS", {"deviceidle"}, CommandOptions::WithTimeout(90).Build(),
2111 SEC_TO_MSEC(10));
2112 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002113
2114 printf("========================================================\n");
2115 printf("== Running Application Services\n");
2116 printf("========================================================\n");
2117
2118 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
2119
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002120 if (include_sensitive_info) {
2121 printf("========================================================\n");
2122 printf("== Running Application Services (non-platform)\n");
2123 printf("========================================================\n");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002124
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002125 // Contains package/component names and potential PII, omit from reports on user builds.
2126 // To get dumps of the active CarrierService(s) on user builds, we supply an argument to the
2127 // carrier_config dumpsys instead.
2128 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
2129 DUMPSYS_COMPONENTS_OPTIONS);
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002130
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002131 printf("========================================================\n");
2132 printf("== Checkins\n");
2133 printf("========================================================\n");
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002134
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002135 // Contains package/component names, omit from reports on user builds.
2136 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
2137 }
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002138
2139 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07002140 printf("== dumpstate: done (id %d)\n", ds.id_);
2141 printf("========================================================\n");
Rhed Jaob5685b32020-08-14 17:19:17 +08002142
2143 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002144 WaitForTask(std::move(dump_board));
Rhed Jaob5685b32020-08-14 17:19:17 +08002145 } else {
2146 RUN_SLOW_FUNCTION_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
2147 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002148}
2149
mukesh agrawal253dad42018-01-23 21:59:59 -08002150// This method collects dumpsys for wifi debugging only
2151static void DumpstateWifiOnly() {
2152 DurationReporter duration_reporter("DUMPSTATE");
2153
Rhed Jaob5685b32020-08-14 17:19:17 +08002154 DumpstateRadioAsRoot();
2155 if (!DropRootUser()) {
2156 return;
2157 }
2158
2159 // Starts thread pool after the root user is dropped. Only one additional
2160 // thread is needed for DumpHals in the DumpstateRadioCommon.
2161 if (ds.dump_pool_) {
2162 ds.dump_pool_->start(/*thread_counts =*/1);
2163 }
2164
mukesh agrawal253dad42018-01-23 21:59:59 -08002165 DumpstateRadioCommon();
2166
2167 printf("========================================================\n");
2168 printf("== Android Framework Services\n");
2169 printf("========================================================\n");
2170
2171 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2172 SEC_TO_MSEC(10));
2173 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
2174 SEC_TO_MSEC(10));
2175
2176 printf("========================================================\n");
2177 printf("== dumpstate: done (id %d)\n", ds.id_);
2178 printf("========================================================\n");
2179}
2180
Nandana Duttcf419a72019-03-14 10:40:17 +00002181Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
Gavin Corkery789d7a52021-02-24 23:52:35 +00002182 const std::string temp_file_pattern = ds.bugreport_internal_dir_ + "/dumptrace_XXXXXX";
Nandana Duttfaafd522019-03-11 09:23:09 +00002183 const size_t buf_size = temp_file_pattern.length() + 1;
2184 std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
2185 memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
2186
2187 // Create a new, empty file to receive all trace dumps.
2188 //
2189 // TODO: This can be simplified once we remove support for the old style
2190 // dumps. We can have a file descriptor passed in to dump_traces instead
2191 // of creating a file, closing it and then reopening it again.
2192 android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
2193 if (fd < 0) {
2194 MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002195 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002196 }
2197
2198 // Nobody should have access to this temporary file except dumpstate, but we
2199 // temporarily grant 'read' to 'others' here because this file is created
2200 // when tombstoned is still running as root, but dumped after dropping. This
2201 // can go away once support for old style dumping has.
2202 const int chmod_ret = fchmod(fd, 0666);
2203 if (chmod_ret < 0) {
2204 MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002205 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002206 }
2207
2208 std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
2209 if (proc.get() == nullptr) {
2210 MYLOGE("opendir /proc failed: %s\n", strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002211 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002212 }
2213
2214 // Number of times process dumping has timed out. If we encounter too many
2215 // failures, we'll give up.
2216 int timeout_failures = 0;
2217 bool dalvik_found = false;
2218
Jayant Chowdharya0a8eb22022-05-20 03:30:09 +00002219 const std::set<int> hal_pids = get_interesting_pids();
Nandana Duttfaafd522019-03-11 09:23:09 +00002220
2221 struct dirent* d;
2222 while ((d = readdir(proc.get()))) {
Nandana Duttcf419a72019-03-14 10:40:17 +00002223 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttfaafd522019-03-11 09:23:09 +00002224 int pid = atoi(d->d_name);
2225 if (pid <= 0) {
2226 continue;
2227 }
2228
Kevin Jeond0f8a982023-04-07 14:27:11 -04002229 // Skip cached processes.
2230 if (IsCached(pid)) {
2231 // For consistency, the header and footer to this message match those
2232 // dumped by debuggerd in the success case.
2233 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
2234 dprintf(fd, "Dump skipped for cached process.\n");
2235 dprintf(fd, "---- end %d ----", pid);
2236 continue;
2237 }
2238
Nandana Duttfaafd522019-03-11 09:23:09 +00002239 const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
2240 std::string exe;
2241 if (!android::base::Readlink(link_name, &exe)) {
2242 continue;
2243 }
2244
2245 bool is_java_process;
2246 if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
2247 // Don't bother dumping backtraces for the zygote.
2248 if (IsZygote(pid)) {
2249 continue;
2250 }
2251
2252 dalvik_found = true;
2253 is_java_process = true;
2254 } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
2255 is_java_process = false;
2256 } else {
2257 // Probably a native process we don't care about, continue.
2258 continue;
2259 }
2260
2261 // If 3 backtrace dumps fail in a row, consider debuggerd dead.
2262 if (timeout_failures == 3) {
2263 dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
2264 break;
2265 }
2266
2267 const uint64_t start = Nanotime();
2268 const int ret = dump_backtrace_to_file_timeout(
Kevin Jeonb8a39362023-04-04 15:00:34 -04002269 pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace, 3, fd);
Nandana Duttfaafd522019-03-11 09:23:09 +00002270
2271 if (ret == -1) {
2272 // For consistency, the header and footer to this message match those
2273 // dumped by debuggerd in the success case.
2274 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
2275 dprintf(fd, "Dump failed, likely due to a timeout.\n");
2276 dprintf(fd, "---- end %d ----", pid);
2277 timeout_failures++;
2278 continue;
2279 }
2280
2281 // We've successfully dumped stack traces, reset the failure count
2282 // and write a summary of the elapsed time to the file and continue with the
2283 // next process.
2284 timeout_failures = 0;
2285
2286 dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
2287 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
2288 }
2289
2290 if (!dalvik_found) {
2291 MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
2292 }
2293
Nandana Duttcf419a72019-03-14 10:40:17 +00002294 *path = file_name_buf.release();
2295 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002296}
2297
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002298static dumpstate_hal_hidl::DumpstateMode GetDumpstateHalModeHidl(
2299 const Dumpstate::BugreportMode bugreport_mode) {
2300 switch (bugreport_mode) {
2301 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2302 return dumpstate_hal_hidl::DumpstateMode::FULL;
2303 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2304 return dumpstate_hal_hidl::DumpstateMode::INTERACTIVE;
2305 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2306 return dumpstate_hal_hidl::DumpstateMode::REMOTE;
2307 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2308 return dumpstate_hal_hidl::DumpstateMode::WEAR;
2309 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2310 return dumpstate_hal_hidl::DumpstateMode::CONNECTIVITY;
2311 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2312 return dumpstate_hal_hidl::DumpstateMode::WIFI;
2313 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2314 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2315 }
2316 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2317}
2318
2319static dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode GetDumpstateHalModeAidl(
2320 const Dumpstate::BugreportMode bugreport_mode) {
2321 switch (bugreport_mode) {
2322 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2323 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::FULL;
2324 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2325 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::INTERACTIVE;
2326 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2327 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::REMOTE;
2328 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2329 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WEAR;
2330 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2331 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::CONNECTIVITY;
2332 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2333 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WIFI;
2334 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2335 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2336 }
2337 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2338}
2339
2340static void DoDumpstateBoardHidl(
2341 const sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_1_0,
2342 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2343 const Dumpstate::BugreportMode bugreport_mode,
2344 const size_t timeout_sec) {
2345
2346 using ScopedNativeHandle =
2347 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
2348 ScopedNativeHandle handle(native_handle_create(static_cast<int>(dumpstate_fds.size()), 0),
2349 [](native_handle_t* handle) {
2350 // we don't close file handle's here
2351 // via native_handle_close(handle)
2352 // instead we let dumpstate_fds close the file handles when
2353 // dumpstate_fds gets destroyed
2354 native_handle_delete(handle);
2355 });
2356 if (handle == nullptr) {
2357 MYLOGE("Could not create native_handle for dumpstate HAL\n");
2358 return;
2359 }
2360
2361 for (size_t i = 0; i < dumpstate_fds.size(); i++) {
2362 handle.get()->data[i] = dumpstate_fds[i].get();
2363 }
2364
2365 // Prefer version 1.1 if available. New devices launching with R are no longer allowed to
2366 // implement just 1.0.
2367 const char* descriptor_to_kill;
2368 using DumpstateBoardTask = std::packaged_task<bool()>;
2369 DumpstateBoardTask dumpstate_board_task;
2370 sp<dumpstate_hal_hidl::IDumpstateDevice> dumpstate_hal(
2371 dumpstate_hal_hidl::IDumpstateDevice::castFrom(dumpstate_hal_1_0));
2372 if (dumpstate_hal != nullptr) {
2373 MYLOGI("Using IDumpstateDevice v1.1 HIDL HAL");
2374
2375 dumpstate_hal_hidl::DumpstateMode dumpstate_hal_mode =
2376 GetDumpstateHalModeHidl(bugreport_mode);
2377
2378 descriptor_to_kill = dumpstate_hal_hidl::IDumpstateDevice::descriptor;
2379 dumpstate_board_task =
2380 DumpstateBoardTask([timeout_sec, dumpstate_hal_mode, dumpstate_hal, &handle]() -> bool {
2381 ::android::hardware::Return<dumpstate_hal_hidl::DumpstateStatus> status =
2382 dumpstate_hal->dumpstateBoard_1_1(handle.get(), dumpstate_hal_mode,
2383 SEC_TO_MSEC(timeout_sec));
2384 if (!status.isOk()) {
2385 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2386 return false;
2387 } else if (status != dumpstate_hal_hidl::DumpstateStatus::OK) {
2388 MYLOGE("dumpstateBoard failed with DumpstateStatus::%s\n",
2389 dumpstate_hal_hidl::toString(status).c_str());
2390 return false;
2391 }
2392 return true;
2393 });
2394 } else {
2395 MYLOGI("Using IDumpstateDevice v1.0 HIDL HAL");
2396
2397 descriptor_to_kill = dumpstate_hal_hidl_1_0::IDumpstateDevice::descriptor;
2398 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal_1_0, &handle]() -> bool {
2399 ::android::hardware::Return<void> status =
2400 dumpstate_hal_1_0->dumpstateBoard(handle.get());
2401 if (!status.isOk()) {
2402 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2403 return false;
2404 }
2405 return true;
2406 });
2407 }
2408 auto result = dumpstate_board_task.get_future();
2409 std::thread(std::move(dumpstate_board_task)).detach();
2410
2411 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2412 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2413 if (!android::base::SetProperty(
2414 "ctl.interface_restart",
2415 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2416 MYLOGE("Couldn't restart dumpstate HAL\n");
2417 }
2418 }
2419 // Wait some time for init to kill dumpstate vendor HAL
2420 constexpr size_t killing_timeout_sec = 10;
2421 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2422 MYLOGE(
2423 "killing dumpstateBoard timed out after %zus, continue and "
2424 "there might be racing in content\n",
2425 killing_timeout_sec);
2426 }
2427}
2428
2429static void DoDumpstateBoardAidl(
2430 const std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal,
2431 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2432 const Dumpstate::BugreportMode bugreport_mode, const size_t timeout_sec) {
2433 MYLOGI("Using IDumpstateDevice AIDL HAL");
2434
2435 const char* descriptor_to_kill;
2436 using DumpstateBoardTask = std::packaged_task<bool()>;
2437 DumpstateBoardTask dumpstate_board_task;
2438 dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode dumpstate_hal_mode =
2439 GetDumpstateHalModeAidl(bugreport_mode);
2440
2441 descriptor_to_kill = dumpstate_hal_aidl::IDumpstateDevice::descriptor;
2442 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal, &dumpstate_fds, dumpstate_hal_mode,
2443 timeout_sec]() -> bool {
2444 auto status = dumpstate_hal->dumpstateBoard(dumpstate_fds, dumpstate_hal_mode, timeout_sec);
2445
2446 if (!status.isOk()) {
2447 MYLOGE("dumpstateBoard failed: %s\n", status.getDescription().c_str());
2448 return false;
2449 }
2450 return true;
2451 });
2452 auto result = dumpstate_board_task.get_future();
2453 std::thread(std::move(dumpstate_board_task)).detach();
2454
2455 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2456 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2457 if (!android::base::SetProperty(
2458 "ctl.interface_restart",
2459 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2460 MYLOGE("Couldn't restart dumpstate HAL\n");
2461 }
2462 }
2463 // Wait some time for init to kill dumpstate vendor HAL
2464 constexpr size_t killing_timeout_sec = 10;
2465 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2466 MYLOGE(
2467 "killing dumpstateBoard timed out after %zus, continue and "
2468 "there might be racing in content\n",
2469 killing_timeout_sec);
2470 }
2471}
2472
2473static std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> GetDumpstateBoardAidlService() {
2474 const std::string aidl_instance_name =
2475 std::string(dumpstate_hal_aidl::IDumpstateDevice::descriptor) + "/default";
2476
2477 if (!AServiceManager_isDeclared(aidl_instance_name.c_str())) {
2478 return nullptr;
2479 }
2480
2481 ndk::SpAIBinder dumpstateBinder(AServiceManager_waitForService(aidl_instance_name.c_str()));
2482
2483 return dumpstate_hal_aidl::IDumpstateDevice::fromBinder(dumpstateBinder);
2484}
2485
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002486void Dumpstate::DumpstateBoard(int out_fd) {
2487 dprintf(out_fd, "========================================================\n");
2488 dprintf(out_fd, "== Board\n");
2489 dprintf(out_fd, "========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08002490
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002491 /*
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002492 * mount debugfs for non-user builds with ro.product.debugfs_restrictions.enabled
Hridya Valsaraju51101602021-04-02 14:32:46 -07002493 * set to true and unmount it after invoking dumpstateBoard_* methods.
2494 * This is to enable debug builds to not have debugfs mounted during runtime.
2495 * It will also ensure that debugfs is only accessed by the dumpstate HAL.
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002496 */
Hridya Valsaraju51101602021-04-02 14:32:46 -07002497 auto mount_debugfs =
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002498 android::base::GetBoolProperty("ro.product.debugfs_restrictions.enabled", false);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002499 if (mount_debugfs) {
2500 RunCommand("mount debugfs", {"mount", "-t", "debugfs", "debugfs", "/sys/kernel/debug"},
2501 AS_ROOT_20);
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002502 RunCommand("chmod debugfs", {"chmod", "0755", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002503 }
2504
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002505 std::vector<std::string> paths;
2506 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07002507 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002508 paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
2509 kDumpstateBoardFiles[i].c_str()));
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002510 remover.emplace_back(android::base::make_scope_guard(
2511 std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002512 }
Jie Song9fbfad02017-06-20 16:29:42 -07002513
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002514 // get dumpstate HAL AIDL implementation
2515 std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal_handle_aidl(
2516 GetDumpstateBoardAidlService());
2517 if (dumpstate_hal_handle_aidl == nullptr) {
2518 MYLOGI("No IDumpstateDevice AIDL implementation\n");
2519 }
2520
2521 // get dumpstate HAL HIDL implementation, only if AIDL HAL implementation not found
2522 sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_handle_hidl_1_0 = nullptr;
2523 if (dumpstate_hal_handle_aidl == nullptr) {
2524 dumpstate_hal_handle_hidl_1_0 = dumpstate_hal_hidl_1_0::IDumpstateDevice::getService();
2525 if (dumpstate_hal_handle_hidl_1_0 == nullptr) {
2526 MYLOGI("No IDumpstateDevice HIDL implementation\n");
2527 }
2528 }
2529
2530 // if neither HIDL nor AIDL implementation found, then return
2531 if (dumpstate_hal_handle_hidl_1_0 == nullptr && dumpstate_hal_handle_aidl == nullptr) {
2532 MYLOGE("Could not find IDumpstateDevice implementation\n");
Wei Wang587eac92018-04-05 12:17:20 -07002533 return;
2534 }
2535
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002536 // this is used to hold the file descriptors and when this variable goes out of scope
2537 // the file descriptors are closed
2538 std::vector<::ndk::ScopedFileDescriptor> dumpstate_fds;
Wei Wang587eac92018-04-05 12:17:20 -07002539
Nandana Dutt5c390032019-03-12 10:52:56 +00002540 // TODO(128270426): Check for consent in between?
Wei Wang587eac92018-04-05 12:17:20 -07002541 for (size_t i = 0; i < paths.size(); i++) {
2542 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
2543
2544 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
2545 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
2546 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
2547 if (fd < 0) {
2548 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
2549 return;
2550 }
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002551
2552 dumpstate_fds.emplace_back(fd.release());
2553 // we call fd.release() here to make sure "fd" does not get closed
2554 // after "fd" goes out of scope after this block.
2555 // "fd" will be closed when "dumpstate_fds" goes out of scope
2556 // i.e. when we exit this function
Wei Wang587eac92018-04-05 12:17:20 -07002557 }
2558
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002559 // Given that bugreport is required to diagnose failures, it's better to set an arbitrary amount
2560 // of timeout for IDumpstateDevice than to block the rest of bugreport. In the timeout case, we
2561 // will kill the HAL and grab whatever it dumped in time.
Michael Eastwood8523ea02022-03-10 16:33:08 -08002562 constexpr size_t timeout_sec = 45;
Wei Wang587eac92018-04-05 12:17:20 -07002563
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002564 if (dumpstate_hal_handle_aidl != nullptr) {
2565 DoDumpstateBoardAidl(dumpstate_hal_handle_aidl, dumpstate_fds, options_->bugreport_mode,
2566 timeout_sec);
2567 } else if (dumpstate_hal_handle_hidl_1_0 != nullptr) {
2568 // run HIDL HAL only if AIDL HAL not found
2569 DoDumpstateBoardHidl(dumpstate_hal_handle_hidl_1_0, dumpstate_fds, options_->bugreport_mode,
2570 timeout_sec);
Wei Wang587eac92018-04-05 12:17:20 -07002571 }
2572
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002573 if (mount_debugfs) {
Hridya Valsaraju51101602021-04-02 14:32:46 -07002574 auto keep_debugfs_mounted =
2575 android::base::GetProperty("persist.dbg.keep_debugfs_mounted", "");
2576 if (keep_debugfs_mounted.empty())
2577 RunCommand("unmount debugfs", {"umount", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002578 }
2579
Wei Wang587eac92018-04-05 12:17:20 -07002580 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
2581 for (size_t i = 0; i < paths.size(); i++) {
2582 struct stat s;
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002583 if (fstat(dumpstate_fds[i].get(), &s) == -1) {
2584 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(), strerror(errno));
Wei Wang587eac92018-04-05 12:17:20 -07002585 file_sizes[i] = -1;
2586 continue;
2587 }
2588 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002589 }
2590
2591 for (size_t i = 0; i < paths.size(); i++) {
2592 if (file_sizes[i] == -1) {
2593 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002594 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002595 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07002596 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002597 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002598 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002599 remover[i].Disable();
2600 EnqueueAddZipEntryAndCleanupIfNeeded(kDumpstateBoardFiles[i], paths[i]);
2601 dprintf(out_fd, "*** See %s entry ***\n", kDumpstateBoardFiles[i].c_str());
Jie Song9fbfad02017-06-20 16:29:42 -07002602 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08002603}
2604
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002605static void ShowUsage() {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002606 fprintf(stderr,
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002607 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o directory] [-p] "
2608 "[-s] [-S] [-q] [-P] [-R] [-L] [-V version]\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002609 " -h: display this help message\n"
2610 " -b: play sound file instead of vibrate, at beginning of job\n"
2611 " -e: play sound file instead of vibrate, at end of job\n"
mhasank2d75c442020-06-11 15:05:25 -07002612 " -o: write to custom directory (only in limited mode)\n"
Abhijeet Kaurbb55a3b2019-06-13 18:07:25 +01002613 " -p: capture screenshot to filename.png\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002614 " -s: write zipped file to control socket (for init)\n"
2615 " -S: write file location to control socket (for init)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002616 " -q: disable vibrate\n"
Abhijeet Kaure370d682019-10-01 16:49:30 +01002617 " -P: send broadcast when started and do progress updates\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002618 " -R: take bugreport in remote mode (shouldn't be used with -P)\n"
Nandana Dutt235864b2019-01-22 12:10:16 +00002619 " -w: start binder service and make it wait for a call to startBugreport\n"
mhasankd451a472020-05-26 18:02:39 -07002620 " -L: output limited information that is safe for submission in feedback reports\n"
Felipe Lemed071c682016-10-20 16:48:00 -07002621 " -v: prints the dumpstate header and exit\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002622}
2623
Wei Liuf87959e2016-08-26 14:51:42 -07002624static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07002625 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07002626}
2627
Felipe Leme1d486fe2016-10-14 18:06:47 -07002628bool Dumpstate::FinishZipFile() {
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002629 // Runs all enqueued adding zip entry and cleanup tasks before finishing the zip file.
2630 if (zip_entry_tasks_) {
2631 zip_entry_tasks_->run(/* do_cancel = */false);
2632 }
2633
Felipe Leme9a523ae2016-10-20 15:10:33 -07002634 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07002635 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07002636 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002637 // Final timestamp
2638 char date[80];
2639 time_t the_real_now_please_stand_up = time(nullptr);
2640 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002641 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002642 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002643
Felipe Leme9a523ae2016-10-20 15:10:33 -07002644 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002645 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08002646 return false;
2647 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07002648 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002649 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08002650 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08002651 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08002652
Felipe Leme0f3fb202016-06-10 17:10:53 -07002653 // Add log file (which contains stderr output) to zip...
2654 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002655 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07002656 MYLOGE("Failed to add dumpstate log to .zip file\n");
2657 return false;
2658 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002659 // TODO: Should truncate the existing file.
2660 // ... and re-open it for further logging.
Nandana Dutta344cb62019-02-22 15:12:35 +00002661 if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
2662 return false;
2663 }
Felipe Leme0f3fb202016-06-10 17:10:53 -07002664 fprintf(stderr, "\n");
2665
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002666 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07002667 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002668 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002669 return false;
2670 }
2671
Felipe Leme1d486fe2016-10-14 18:06:47 -07002672 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
2673 ds.zip_file.reset(nullptr);
2674
Felipe Lemee9d2c542016-11-15 11:48:26 -08002675 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002676 android::os::UnlinkAndLogOnError(tmp_path_);
Felipe Lemec4eee562016-04-21 15:42:55 -07002677
Felipe Leme1e9edc62015-12-21 16:02:13 -08002678 return true;
2679}
Felipe Leme6e01fa62015-11-11 19:35:14 -08002680
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00002681static void SendBroadcast(const std::string& action,
2682 const std::vector<std::string>& args,
2683 int32_t user_id) {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002684 // clang-format off
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00002685 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user",
2686 std::to_string(user_id), "--receiver-foreground",
2687 "--receiver-include-background", "-a", action};
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002688 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08002689
2690 am.insert(am.end(), args.begin(), args.end());
2691
Felipe Leme8d2410e2017-02-08 09:46:08 -08002692 RunCommand("", am,
2693 CommandOptions::WithTimeout(20)
2694 .Log("Sending broadcast: '%s'\n")
2695 .Always()
2696 .DropRoot()
2697 .RedirectStderr()
2698 .Build());
2699}
2700
Felipe Leme35b8cf12017-02-10 15:47:29 -08002701static void Vibrate(int duration_ms) {
2702 // clang-format off
Lais Andrade51156962021-02-22 19:21:35 +00002703 std::vector<std::string> args = {"cmd", "vibrator_manager", "synced", "-f", "-d", "dumpstate",
2704 "oneshot", std::to_string(duration_ms)};
2705 RunCommand("", args,
Felipe Leme35b8cf12017-02-10 15:47:29 -08002706 CommandOptions::WithTimeout(10)
2707 .Log("Vibrate: '%s'\n")
2708 .Always()
2709 .Build());
2710 // clang-format on
2711}
2712
Nandana Dutt979388e2018-11-30 16:48:55 +00002713static void MaybeResolveSymlink(std::string* path) {
2714 std::string resolved_path;
2715 if (android::base::Readlink(*path, &resolved_path)) {
2716 *path = resolved_path;
2717 }
2718}
2719
Nandana Dutt4be45d12018-09-26 15:04:23 +01002720/*
2721 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002722 * and adds the version file. Return false if zip_file could not be open to write.
Nandana Dutt4be45d12018-09-26 15:04:23 +01002723 */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002724static bool PrepareToWriteToFile() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002725 MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2726
Nandana Dutt4be45d12018-09-26 15:04:23 +01002727 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2728 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002729 ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002730 char date[80];
2731 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2732 ds.name_ = date;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002733
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002734 if (ds.options_->telephony_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002735 ds.base_name_ += "-telephony";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002736 } else if (ds.options_->wifi_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002737 ds.base_name_ += "-wifi";
2738 }
2739
Paul Chang0d2aad72020-02-13 20:04:03 +08002740 if (ds.options_->do_screenshot) {
Nandana Dutt9d17b942020-03-26 10:02:59 +00002741 ds.screenshot_path_ = ds.GetPath(ds.CalledByApi() ? "-png.tmp" : ".png");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002742 }
2743 ds.tmp_path_ = ds.GetPath(".tmp");
2744 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2745
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01002746 std::string destination = ds.CalledByApi()
Nandana Dutt54dbd672019-01-11 12:58:05 +00002747 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
Nandana Dutt9a76d202019-01-21 15:56:48 +00002748 : ds.bugreport_internal_dir_.c_str();
Nandana Dutt4be45d12018-09-26 15:04:23 +01002749 MYLOGD(
Nandana Dutt235c6672019-11-14 15:22:32 +00002750 "Bugreport dir: [%s] "
2751 "Base name: [%s] "
2752 "Suffix: [%s] "
2753 "Log path: [%s] "
2754 "Temporary path: [%s] "
2755 "Screenshot path: [%s]\n",
Nandana Dutt9a76d202019-01-21 15:56:48 +00002756 destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2757 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002758
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002759 ds.path_ = ds.GetPath(ds.CalledByApi() ? "-zip.tmp" : ".zip");
2760 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2761 create_parent_dirs(ds.path_.c_str());
2762 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2763 if (ds.zip_file == nullptr) {
2764 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2765 return false;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002766 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002767 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2768 ds.AddTextZipEntry("version.txt", ds.version_);
2769 return true;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002770}
2771
2772/*
Abhijeet Kaure370d682019-10-01 16:49:30 +01002773 * Finalizes writing to the file by zipping the tmp file to the final location,
Nandana Dutt4be45d12018-09-26 15:04:23 +01002774 * printing zipped file status, etc.
2775 */
2776static void FinalizeFile() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002777 bool do_text_file = !ds.FinishZipFile();
2778 if (do_text_file) {
2779 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002780 }
mhasank2d75c442020-06-11 15:05:25 -07002781
2782 std::string final_path = ds.path_;
2783 if (ds.options_->OutputToCustomFile()) {
mhasank3a4cfb42020-06-15 18:06:43 -07002784 final_path = ds.GetPath(ds.options_->out_dir, ".zip");
mhasank2d75c442020-06-11 15:05:25 -07002785 android::os::CopyFileToFile(ds.path_, final_path);
2786 }
2787
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002788 if (ds.options_->stream_to_socket) {
2789 android::os::CopyFileToFd(ds.path_, ds.control_socket_fd_);
2790 } else if (ds.options_->progress_updates_to_socket) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002791 if (do_text_file) {
2792 dprintf(ds.control_socket_fd_,
2793 "FAIL:could not create zip file, check %s "
2794 "for more details\n",
2795 ds.log_path_.c_str());
2796 } else {
mhasank2d75c442020-06-11 15:05:25 -07002797 dprintf(ds.control_socket_fd_, "OK:%s\n", final_path.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002798 }
2799 }
2800}
2801
Nandana Dutt4be45d12018-09-26 15:04:23 +01002802
Nandana Dutt58d72e22018-11-16 10:30:48 +00002803static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2804 switch (mode) {
2805 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2806 return "BUGREPORT_FULL";
2807 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2808 return "BUGREPORT_INTERACTIVE";
2809 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2810 return "BUGREPORT_REMOTE";
2811 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2812 return "BUGREPORT_WEAR";
2813 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2814 return "BUGREPORT_TELEPHONY";
2815 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2816 return "BUGREPORT_WIFI";
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002817 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2818 return "BUGREPORT_DEFAULT";
Nandana Dutt58d72e22018-11-16 10:30:48 +00002819 }
2820}
2821
Steven Leeb573eb82022-11-29 22:31:35 +08002822static bool IsConsentlessBugreportAllowed(const Dumpstate::DumpOptions& options) {
2823 // only BUGREPORT_TELEPHONY does not allow using consentless bugreport
2824 return !options.telephony_only;
2825}
2826
Paul Changf59c2b72020-03-10 02:08:55 +08002827static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options,
2828 bool is_screenshot_requested) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002829 // Modify com.android.shell.BugreportProgressService#isDefaultScreenshotRequired as well for
2830 // default system screenshots.
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002831 options->bugreport_mode = mode;
2832 options->bugreport_mode_string = ModeToString(mode);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002833 switch (mode) {
2834 case Dumpstate::BugreportMode::BUGREPORT_FULL:
Paul Changf59c2b72020-03-10 02:08:55 +08002835 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002836 break;
2837 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002838 // Currently, the dumpstate binder is only used by Shell to update progress.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002839 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002840 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002841 break;
2842 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002843 options->do_vibrate = false;
2844 options->is_remote_mode = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002845 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002846 break;
2847 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
Robert Ginda55ecebd2023-04-03 22:53:13 +00002848 options->do_vibrate = false;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002849 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002850 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002851 break;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002852 // TODO(b/148168577) rename TELEPHONY everywhere to CONNECTIVITY.
Nandana Dutt58d72e22018-11-16 10:30:48 +00002853 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002854 options->telephony_only = true;
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002855 options->do_progress_updates = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002856 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002857 break;
2858 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002859 options->wifi_only = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002860 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002861 break;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002862 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2863 break;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002864 }
2865}
2866
Nandana Dutt58d72e22018-11-16 10:30:48 +00002867static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
Nandana Dutt235c6672019-11-14 15:22:32 +00002868 MYLOGI(
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002869 "do_vibrate: %d stream_to_socket: %d progress_updates_to_socket: %d do_screenshot: %d "
Rhed Jao25f50e02020-08-20 00:10:32 +08002870 "is_remote_mode: %d show_header_only: %d telephony_only: %d "
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002871 "wifi_only: %d do_progress_updates: %d fd: %d bugreport_mode: %s "
mhasankd451a472020-05-26 18:02:39 -07002872 "limited_only: %d args: %s\n",
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002873 options.do_vibrate, options.stream_to_socket, options.progress_updates_to_socket,
Paul Chang0d2aad72020-02-13 20:04:03 +08002874 options.do_screenshot, options.is_remote_mode, options.show_header_only,
Rhed Jao25f50e02020-08-20 00:10:32 +08002875 options.telephony_only, options.wifi_only,
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002876 options.do_progress_updates, options.bugreport_fd.get(),
2877 options.bugreport_mode_string.c_str(),
2878 options.limited_only, options.args.c_str());
Nandana Dutt58d72e22018-11-16 10:30:48 +00002879}
2880
Nandana Dutt54dbd672019-01-11 12:58:05 +00002881void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
Kean Mariotti306633e2022-09-05 16:30:47 +00002882 int bugreport_flags,
Nandana Dutt54dbd672019-01-11 12:58:05 +00002883 const android::base::unique_fd& bugreport_fd_in,
Paul Changf59c2b72020-03-10 02:08:55 +08002884 const android::base::unique_fd& screenshot_fd_in,
2885 bool is_screenshot_requested) {
Kean Mariotti306633e2022-09-05 16:30:47 +00002886 this->use_predumped_ui_data = bugreport_flags & BugreportFlag::BUGREPORT_USE_PREDUMPED_UI_DATA;
Gavin Corkerya44686c2022-11-23 18:16:51 +00002887 this->is_consent_deferred = bugreport_flags & BugreportFlag::BUGREPORT_FLAG_DEFER_CONSENT;
Nandana Dutt54dbd672019-01-11 12:58:05 +00002888 // Duplicate the fds because the passed in fds don't outlive the binder transaction.
Todd Frederick621533f2022-03-26 02:54:17 +00002889 bugreport_fd.reset(fcntl(bugreport_fd_in.get(), F_DUPFD_CLOEXEC, 0));
2890 screenshot_fd.reset(fcntl(screenshot_fd_in.get(), F_DUPFD_CLOEXEC, 0));
Nandana Dutt58d72e22018-11-16 10:30:48 +00002891
Paul Changf59c2b72020-03-10 02:08:55 +08002892 SetOptionsFromMode(bugreport_mode, this, is_screenshot_requested);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002893}
2894
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002895Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
2896 RunStatus status = RunStatus::OK;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002897 int c;
mhasankd451a472020-05-26 18:02:39 -07002898 while ((c = getopt(argc, argv, "dho:svqzpLPBRSV:w")) != -1) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002899 switch (c) {
2900 // clang-format off
mhasank3a4cfb42020-06-15 18:06:43 -07002901 case 'o': out_dir = optarg; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002902 case 's': stream_to_socket = true; break;
2903 case 'S': progress_updates_to_socket = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002904 case 'v': show_header_only = true; break;
2905 case 'q': do_vibrate = false; break;
Paul Chang0d2aad72020-02-13 20:04:03 +08002906 case 'p': do_screenshot = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002907 case 'P': do_progress_updates = true; break;
2908 case 'R': is_remote_mode = true; break;
mhasankd451a472020-05-26 18:02:39 -07002909 case 'L': limited_only = true; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002910 case 'V':
2911 case 'd':
2912 case 'z':
2913 // compatibility no-op
2914 break;
Nandana Dutt235864b2019-01-22 12:10:16 +00002915 case 'w':
2916 // This was already processed
2917 break;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002918 case 'h':
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002919 status = RunStatus::HELP;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002920 break;
2921 default:
2922 fprintf(stderr, "Invalid option: %c\n", c);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002923 status = RunStatus::INVALID_INPUT;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002924 break;
2925 // clang-format on
2926 }
2927 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08002928
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002929 for (int i = 0; i < argc; i++) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002930 args += argv[i];
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002931 if (i < argc - 1) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002932 args += " ";
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002933 }
2934 }
2935
2936 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
2937 optind = 1;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002938
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002939 return status;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002940}
2941
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002942bool Dumpstate::DumpOptions::ValidateOptions() const {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002943 if (bugreport_fd.get() != -1 && stream_to_socket) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002944 return false;
2945 }
2946
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002947 if ((progress_updates_to_socket || do_progress_updates) && stream_to_socket) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002948 return false;
2949 }
2950
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002951 if (is_remote_mode && (do_progress_updates || stream_to_socket)) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002952 return false;
2953 }
2954 return true;
2955}
2956
Nandana Dutt197661d2018-11-16 16:40:21 +00002957void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
2958 options_ = std::move(options);
2959}
2960
Abhijeet Kaura407fb82020-03-27 12:51:12 +00002961void Dumpstate::Initialize() {
2962 /* gets the sequential id */
2963 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
2964 id_ = ++last_id;
2965 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
2966}
2967
Nandana Duttd2f5f082019-01-18 17:13:52 +00002968Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
2969 Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
Gavin Corkerya44686c2022-11-23 18:16:51 +00002970 HandleRunStatus(status);
2971 return status;
2972}
2973
2974Dumpstate::RunStatus Dumpstate::Retrieve(int32_t calling_uid, const std::string& calling_package) {
2975 Dumpstate::RunStatus status = RetrieveInternal(calling_uid, calling_package);
2976 HandleRunStatus(status);
2977 return status;
2978}
2979
2980Dumpstate::RunStatus Dumpstate::RetrieveInternal(int32_t calling_uid,
2981 const std::string& calling_package) {
2982 consent_callback_ = new ConsentCallback();
2983 const String16 incidentcompanion("incidentcompanion");
2984 sp<android::IBinder> ics(
2985 defaultServiceManager()->checkService(incidentcompanion));
2986 android::String16 package(calling_package.c_str());
2987 if (ics != nullptr) {
2988 MYLOGD("Checking user consent via incidentcompanion service\n");
2989 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
2990 calling_uid, package, String16(), String16(),
2991 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
2992 } else {
2993 MYLOGD(
2994 "Unable to check user consent; incidentcompanion service unavailable\n");
2995 return RunStatus::USER_CONSENT_TIMED_OUT;
2996 }
2997 UserConsentResult consent_result = consent_callback_->getResult();
2998 int timeout_ms = 30 * 1000;
2999 while (consent_result == UserConsentResult::UNAVAILABLE &&
3000 consent_callback_->getElapsedTimeMs() < timeout_ms) {
3001 sleep(1);
3002 consent_result = consent_callback_->getResult();
3003 }
3004 if (consent_result == UserConsentResult::DENIED) {
3005 return RunStatus::USER_CONSENT_DENIED;
3006 }
3007 if (consent_result == UserConsentResult::UNAVAILABLE) {
3008 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3009 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3010 consent_callback_.get());
3011 return RunStatus::USER_CONSENT_TIMED_OUT;
3012 }
3013
3014 bool copy_succeeded =
3015 android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
3016 if (copy_succeeded) {
3017 android::os::UnlinkAndLogOnError(path_);
3018 }
3019 return copy_succeeded ? Dumpstate::RunStatus::OK
3020 : Dumpstate::RunStatus::ERROR;
3021}
3022
3023void Dumpstate::HandleRunStatus(Dumpstate::RunStatus status) {
3024 if (listener_ != nullptr) {
Nandana Duttbabf6c72019-01-15 14:11:12 +00003025 switch (status) {
3026 case Dumpstate::RunStatus::OK:
Gavin Corkerya44686c2022-11-23 18:16:51 +00003027 listener_->onFinished(path_.c_str());
Nandana Duttbabf6c72019-01-15 14:11:12 +00003028 break;
3029 case Dumpstate::RunStatus::HELP:
3030 break;
3031 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003032 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00003033 break;
3034 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003035 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
3036 break;
3037 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3038 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
3039 break;
3040 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
3041 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00003042 break;
3043 }
3044 }
Nandana Duttbabf6c72019-01-15 14:11:12 +00003045}
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003046void Dumpstate::Cancel() {
3047 CleanupTmpFiles();
3048 android::os::UnlinkAndLogOnError(log_path_);
3049 for (int i = 0; i < NUM_OF_DUMPS; i++) {
3050 android::os::UnlinkAndLogOnError(ds.bugreport_internal_dir_ + "/" +
3051 kDumpstateBoardFiles[i]);
3052 }
3053 tombstone_data_.clear();
3054 anr_data_.clear();
Andy Hungd62f7e62024-01-11 15:47:52 -08003055 anr_trace_data_.clear();
Woody Lin20767a92022-11-29 15:50:24 +08003056 shutdown_checkpoints_.clear();
Rhed Jao0daac912020-08-21 14:48:20 +08003057
3058 // Instead of shutdown the pool, we delete temporary files directly since
3059 // shutdown blocking the call.
3060 if (dump_pool_) {
3061 dump_pool_->deleteTempFiles();
3062 }
3063 if (zip_entry_tasks_) {
3064 zip_entry_tasks_->run(/*do_cancel =*/ true);
3065 }
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003066}
3067
Kean Mariotti306633e2022-09-05 16:30:47 +00003068void Dumpstate::PreDumpUiData() {
3069 MaybeSnapshotUiTraces();
3070}
3071
Nandana Dutt979388e2018-11-30 16:48:55 +00003072/*
3073 * Dumps relevant information to a bugreport based on the given options.
3074 *
3075 * The bugreport can be dumped to a file or streamed to a socket.
3076 *
3077 * How dumping to file works:
3078 * stdout is redirected to a temporary file. This will later become the main bugreport entry.
3079 * stderr is redirected a log file.
3080 *
3081 * The temporary bugreport is then populated via printfs, dumping contents of files and
3082 * output of commands to stdout.
3083 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003084 * A bunch of other files and dumps are added to the zip archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00003085 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003086 * The temporary bugreport file and the log file also get added to the archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00003087 *
mhasank2d75c442020-06-11 15:05:25 -07003088 * Bugreports are first generated in a local directory and later copied to the caller's fd
3089 * or directory if supplied.
Nandana Dutt979388e2018-11-30 16:48:55 +00003090 */
Nandana Duttd2f5f082019-01-18 17:13:52 +00003091Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
3092 const std::string& calling_package) {
Rhed Jao5377d792020-07-16 17:37:39 +08003093 DurationReporter duration_reporter("RUN INTERNAL", /* logcat_only = */true);
Nandana Dutt979388e2018-11-30 16:48:55 +00003094 LogDumpOptions(*options_);
Nandana Dutt197661d2018-11-16 16:40:21 +00003095 if (!options_->ValidateOptions()) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00003096 MYLOGE("Invalid options specified\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003097 return RunStatus::INVALID_INPUT;
3098 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003099 /* set as high priority, and protect from OOM killer */
3100 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003101
Felipe Lemed071c682016-10-20 16:48:00 -07003102 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07003103 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003104 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003105 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003106 } else {
3107 /* fallback to kernels <= 2.6.35 */
3108 oom_adj = fopen("/proc/self/oom_adj", "we");
3109 if (oom_adj) {
3110 fputs("-17", oom_adj);
3111 fclose(oom_adj);
3112 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003113 }
3114
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003115 if (version_ == VERSION_DEFAULT) {
3116 version_ = VERSION_CURRENT;
Michal Karpinski4db754f2015-12-11 18:04:32 +00003117 }
3118
Chris Morin5a50d482022-02-01 17:41:18 -08003119 if (version_ != VERSION_CURRENT) {
3120 MYLOGE("invalid version requested ('%s'); supported values are: ('%s', '%s')\n",
3121 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003122 return RunStatus::INVALID_INPUT;
Felipe Lemed071c682016-10-20 16:48:00 -07003123 }
3124
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003125 if (options_->show_header_only) {
3126 PrintHeader();
3127 return RunStatus::OK;
Felipe Lemed071c682016-10-20 16:48:00 -07003128 }
3129
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003130 MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n",
3131 calling_uid, calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003132
Felipe Leme7447d7c2016-11-03 18:12:22 -07003133 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003134 std::string stats_path =
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003135 android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003136 progress_.reset(new Progress(stats_path));
Felipe Leme7447d7c2016-11-03 18:12:22 -07003137
Sahana Raof35ed432019-07-12 10:47:52 +01003138 if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
3139 MYLOGE("Failed to acquire wake lock: %s\n", strerror(errno));
3140 } else {
3141 // Wake lock will be released automatically on process death
3142 MYLOGD("Wake lock acquired.\n");
3143 }
3144
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08003145 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07003146
Felipe Lemef0292972016-11-22 13:57:05 -08003147 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07003148 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
3149 }
3150
Kevin Jeonfa64e642023-07-27 11:36:41 -04003151 if (PropertiesHelper::IsStrictRun()) {
3152 MYLOGI(
3153 "Running on strict-run mode, which has shorter timeouts "
3154 "(to disable, call 'setprop dumpstate.strict_run false')\n");
3155 }
3156
Nandana Dutt235c6672019-11-14 15:22:32 +00003157 MYLOGI("dumpstate info: id=%d, args='%s', bugreport_mode= %s bugreport format version: %s\n",
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00003158 id_, options_->args.c_str(), options_->bugreport_mode_string.c_str(), version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08003159
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003160 do_early_screenshot_ = options_->do_progress_updates;
Felipe Lemee338bf62015-12-07 14:03:50 -08003161
Christopher Ferrised9354f2014-10-01 17:35:01 -07003162 // If we are going to use a socket, do it as early as possible
3163 // to avoid timeouts from bugreport.
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003164 if (options_->stream_to_socket || options_->progress_updates_to_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07003165 MYLOGD("Opening control socket\n");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003166 control_socket_fd_ = open_socket_fn_("dumpstate");
Nandana Dutta344cb62019-02-22 15:12:35 +00003167 if (control_socket_fd_ == -1) {
3168 return ERROR;
3169 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003170 if (options_->progress_updates_to_socket) {
3171 options_->do_progress_updates = 1;
3172 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07003173 }
3174
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003175 if (!PrepareToWriteToFile()) {
3176 return ERROR;
3177 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08003178
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003179 // Interactive, wear & telephony modes are default to true.
3180 // and may enable from cli option or when using control socket
3181 if (options_->do_progress_updates) {
3182 // clang-format off
3183 std::vector<std::string> am_args = {
3184 "--receiver-permission", "android.permission.DUMP",
3185 };
3186 // clang-format on
3187 // Send STARTED broadcast for apps that listen to bugreport generation events
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003188 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED",
3189 am_args, multiuser_get_user_id(calling_uid));
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003190 if (options_->progress_updates_to_socket) {
3191 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08003192 }
3193 }
3194
Nick Kralevichf3599b32016-01-25 15:05:16 -08003195 /* read /proc/cmdline before dropping root */
3196 FILE *cmdline = fopen("/proc/cmdline", "re");
3197 if (cmdline) {
3198 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
3199 fclose(cmdline);
3200 }
3201
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003202 if (options_->do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08003203 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05003204 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003205
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003206 if (zip_file != nullptr) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003207 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
3208 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003209 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08003210 }
3211 }
3212
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003213 int dup_stdout_fd;
3214 int dup_stderr_fd;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003215 // Redirect stderr to log_path_ for debugging.
3216 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
3217 if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
3218 return ERROR;
3219 }
3220 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
3221 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
3222 strerror(errno));
3223 }
Nandana Dutt979388e2018-11-30 16:48:55 +00003224
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003225 // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
3226 // moved into zip file later, if zipping.
3227 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
3228 // TODO: why not write to a file instead of stdout to overcome this problem?
3229 /* TODO: rather than generating a text file now and zipping it later,
3230 it would be more efficient to redirect stdout to the zip entry
3231 directly, but the libziparchive doesn't support that option yet. */
3232 if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
3233 return ERROR;
3234 }
3235 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
3236 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
3237 tmp_path_.c_str(), strerror(errno));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003238 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08003239
3240 // Don't buffer stdout
3241 setvbuf(stdout, nullptr, _IONBF, 0);
3242
Rhed Jao5377d792020-07-16 17:37:39 +08003243 // Enable the parallel run if the client requests to output to a file.
3244 EnableParallelRunIfNeeded();
3245 // Using scope guard to make sure the dump pool can be shut down correctly.
3246 auto scope_guard_to_shutdown_pool = android::base::make_scope_guard([=]() {
3247 ShutdownDumpPool();
3248 });
3249
Felipe Leme608385d2016-02-01 10:35:38 -08003250 // NOTE: there should be no stdout output until now, otherwise it would break the header.
3251 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08003252 // duration is logged into MYLOG instead.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003253 PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003254
Gavin Corkery6968f552020-11-22 18:09:05 +00003255 bool is_dumpstate_restricted = options_->telephony_only
3256 || options_->wifi_only
3257 || options_->limited_only;
3258 if (!is_dumpstate_restricted) {
Paul Chang0d2aad72020-02-13 20:04:03 +08003259 // Invoke critical dumpsys first to preserve system state, before doing anything else.
Jichao Lie89d9c12019-11-21 19:02:51 -08003260 RunDumpsysCritical();
Gavin Corkery6968f552020-11-22 18:09:05 +00003261 }
3262 MaybeTakeEarlyScreenshot();
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003263
3264 if (!is_dumpstate_restricted) {
3265 // Snapshot the system trace now (if running) to avoid that dumpstate's
3266 // own activity pushes out interesting data from the trace ring buffer.
3267 // The trace file is added to the zip by MaybeAddSystemTraceToZip().
3268 MaybeSnapshotSystemTrace();
Yohei Yukawa95305b32021-03-09 07:54:27 -08003269
Kean Mariotti306633e2022-09-05 16:30:47 +00003270 // Snapshot the UI traces now (if running).
3271 // The trace files will be added to bugreport later.
3272 MaybeSnapshotUiTraces();
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003273 }
Gavin Corkery6968f552020-11-22 18:09:05 +00003274 onUiIntensiveBugreportDumpsFinished(calling_uid);
3275 MaybeCheckUserConsent(calling_uid, calling_package);
3276 if (options_->telephony_only) {
3277 DumpstateTelephonyOnly(calling_package);
3278 } else if (options_->wifi_only) {
3279 DumpstateWifiOnly();
3280 } else if (options_->limited_only) {
3281 DumpstateLimitedOnly();
3282 } else {
Nandana Dutt4be45d12018-09-26 15:04:23 +01003283 // Dump state for the default case. This also drops root.
Jichao Lie89d9c12019-11-21 19:02:51 -08003284 RunStatus s = DumpstateDefaultAfterCritical();
Nandana Dutt5c390032019-03-12 10:52:56 +00003285 if (s != RunStatus::OK) {
Nandana Duttaac6f582019-07-26 14:32:47 +01003286 if (s == RunStatus::USER_CONSENT_DENIED) {
Nandana Dutt5c390032019-03-12 10:52:56 +00003287 HandleUserConsentDenied();
3288 }
3289 return s;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08003290 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07003291 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07003292
Felipe Leme55b42a62015-11-10 17:39:08 -08003293 /* close output if needed */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003294 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003295
Abhijeet Kaure370d682019-10-01 16:49:30 +01003296 // Zip the (now complete) .tmp file within the internal directory.
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003297 ATRACE_BEGIN("FinalizeFile");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003298 FinalizeFile();
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003299 ATRACE_END();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003300
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003301 // Share the final file with the caller if the user has consented or Shell is the caller.
Nandana Duttd2f5f082019-01-18 17:13:52 +00003302 Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
Gavin Corkerya44686c2022-11-23 18:16:51 +00003303 if (CalledByApi() && !options_->is_consent_deferred) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003304 status = CopyBugreportIfUserConsented(calling_uid);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003305 if (status != Dumpstate::RunStatus::OK &&
3306 status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3307 // Do an early return if there were errors. We make an exception for consent
3308 // timing out because it's possible the user got distracted. In this case the
3309 // bugreport is not shared but made available for manual retrieval.
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003310 MYLOGI("User denied consent. Returning\n");
Nandana Duttd2f5f082019-01-18 17:13:52 +00003311 return status;
3312 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003313 if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3314 MYLOGI(
3315 "Did not receive user consent yet."
3316 " Will not copy the bugreport artifacts to caller.\n");
Abhijeet Kaur57627412019-04-17 16:00:09 +01003317 const String16 incidentcompanion("incidentcompanion");
3318 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
3319 if (ics != nullptr) {
3320 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3321 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3322 consent_callback_.get());
3323 } else {
3324 MYLOGD("Unable to cancel user consent; incidentcompanion service unavailable\n");
3325 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003326 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003327 }
3328
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003329 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003330 if (options_->do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09003331 for (int i = 0; i < 3; i++) {
3332 Vibrate(75);
3333 usleep((75 + 50) * 1000);
3334 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003335 }
3336
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003337 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
3338 progress_->GetInitialMax());
3339 progress_->Save();
3340 MYLOGI("done (id %d)\n", id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003341
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003342 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08003343
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003344 if (control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07003345 MYLOGD("Closing control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003346 close(control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07003347 }
3348
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003349 tombstone_data_.clear();
3350 anr_data_.clear();
Andy Hungd62f7e62024-01-11 15:47:52 -08003351 anr_trace_data_.clear();
Woody Lin20767a92022-11-29 15:50:24 +08003352 shutdown_checkpoints_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01003353
Nandana Duttd2f5f082019-01-18 17:13:52 +00003354 return (consent_callback_ != nullptr &&
3355 consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
3356 ? USER_CONSENT_TIMED_OUT
3357 : RunStatus::OK;
3358}
3359
Paul Chang0d2aad72020-02-13 20:04:03 +08003360void Dumpstate::MaybeTakeEarlyScreenshot() {
3361 if (!options_->do_screenshot || !do_early_screenshot_) {
3362 return;
3363 }
3364
3365 TakeScreenshot();
3366}
3367
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003368void Dumpstate::MaybeSnapshotSystemTrace() {
3369 // If a background system trace is happening and is marked as "suitable for
3370 // bugreport" (i.e. bugreport_score > 0 in the trace config), this command
3371 // will stop it and serialize into SYSTEM_TRACE_SNAPSHOT. In the (likely)
3372 // case that no trace is ongoing, this command is a no-op.
3373 // Note: this should not be enqueued as we need to freeze the trace before
3374 // dumpstate starts. Otherwise the trace ring buffers will contain mostly
3375 // the dumpstate's own activity which is irrelevant.
3376 int res = RunCommand(
3377 "SERIALIZE PERFETTO TRACE",
3378 {"perfetto", "--save-for-bugreport"},
3379 CommandOptions::WithTimeout(10)
3380 .DropRoot()
3381 .CloseAllFileDescriptorsOnExec()
3382 .Build());
3383 has_system_trace_ = res == 0;
3384 // MaybeAddSystemTraceToZip() will take care of copying the trace in the zip
3385 // file in the later stages.
3386}
3387
Kean Mariotti306633e2022-09-05 16:30:47 +00003388void Dumpstate::MaybeSnapshotUiTraces() {
3389 if (PropertiesHelper::IsUserBuild() || options_->use_predumped_ui_data) {
3390 return;
3391 }
Hongwei Wang9ec5c252023-01-24 15:09:59 -08003392
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003393 const std::vector<std::vector<std::string>> dumpTracesForBugReportCommands = {
3394 {"dumpsys", "activity", "service", "SystemUIService", "WMShell", "protolog",
3395 "save-for-bugreport"},
3396 {"dumpsys", "activity", "service", "SystemUIService", "WMShell", "transitions", "tracing",
3397 "save-for-bugreport"},
3398 {"cmd", "input_method", "tracing", "save-for-bugreport"},
3399 {"cmd", "window", "tracing", "save-for-bugreport"},
3400 {"cmd", "window", "shell", "tracing", "save-for-bugreport"},
3401 };
Hongwei Wang39229132023-01-24 15:09:59 -08003402
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003403 for (const auto& command : dumpTracesForBugReportCommands) {
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003404 RunCommand(
3405 // Empty name because it's not intended to be classified as a bugreport section.
3406 // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003407 "", command,
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003408 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
3409 }
Kean Mariotti306633e2022-09-05 16:30:47 +00003410
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003411 // This command needs to be run as root
Kean Mariotti306633e2022-09-05 16:30:47 +00003412 static const auto SURFACEFLINGER_COMMAND_SAVE_ALL_TRACES = std::vector<std::string> {
3413 "service", "call", "SurfaceFlinger", "1042"
3414 };
3415 // Empty name because it's not intended to be classified as a bugreport section.
3416 // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
3417 RunCommand(
3418 "", SURFACEFLINGER_COMMAND_SAVE_ALL_TRACES,
3419 CommandOptions::WithTimeout(10).Always().AsRoot().RedirectStderr().Build());
3420}
3421
3422void Dumpstate::MaybePostProcessUiTraces() {
3423 if (PropertiesHelper::IsUserBuild()) {
3424 return;
3425 }
3426
3427 RunCommand(
3428 // Empty name because it's not intended to be classified as a bugreport section.
3429 // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
3430 "", {
3431 "/system/xbin/su", "system",
3432 "/system/bin/layertracegenerator",
3433 "/data/misc/wmtrace/transactions_trace.winscope",
3434 "/data/misc/wmtrace/layers_trace_from_transactions.winscope"
3435 },
3436 CommandOptions::WithTimeout(120).Always().RedirectStderr().Build());
3437}
3438
3439void Dumpstate::MaybeAddUiTracesToZip() {
3440 if (PropertiesHelper::IsUserBuild()) {
3441 return;
3442 }
3443
3444 ds.AddDir(WMTRACE_DATA_DIR, false);
Yohei Yukawa95305b32021-03-09 07:54:27 -08003445}
3446
Paul Changeb4b4642020-05-28 22:05:47 +08003447void Dumpstate::onUiIntensiveBugreportDumpsFinished(int32_t calling_uid) {
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003448 if (multiuser_get_app_id(calling_uid) == AID_SHELL || !CalledByApi()) {
Paul Changc490e662020-04-11 18:14:09 +08003449 return;
3450 }
3451 if (listener_ != nullptr) {
3452 // Let listener know ui intensive bugreport dumps are finished, then it can do event
3453 // handling if required.
Paul Changeb4b4642020-05-28 22:05:47 +08003454 listener_->onUiIntensiveBugreportDumpsFinished();
Paul Changc490e662020-04-11 18:14:09 +08003455 }
3456}
3457
Jichao Lie89d9c12019-11-21 19:02:51 -08003458void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) {
Gavin Corkerya44686c2022-11-23 18:16:51 +00003459 if (multiuser_get_app_id(calling_uid) == AID_SHELL ||
3460 !CalledByApi() || options_->is_consent_deferred) {
3461 // No need to get consent for shell triggered dumpstates, or not
3462 // through bugreporting API (i.e. no fd to copy back), or when consent
3463 // is deferred.
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003464 return;
3465 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003466 consent_callback_ = new ConsentCallback();
3467 const String16 incidentcompanion("incidentcompanion");
3468 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
Jichao Lie89d9c12019-11-21 19:02:51 -08003469 android::String16 package(calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003470 if (ics != nullptr) {
3471 MYLOGD("Checking user consent via incidentcompanion service\n");
Steven Leeb573eb82022-11-29 22:31:35 +08003472 int flags = 0x1; // IncidentManager.FLAG_CONFIRMATION_DIALOG
3473 if (IsConsentlessBugreportAllowed(*options_)) {
3474 flags |= 0x2; // IncidentManager.FLAG_ALLOW_CONSENTLESS_BUGREPORT
3475 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003476 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
Steven Leeb573eb82022-11-29 22:31:35 +08003477 calling_uid, package, String16(), String16(), flags, consent_callback_.get());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003478 } else {
3479 MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
3480 }
3481}
3482
Nandana Dutt5c390032019-03-12 10:52:56 +00003483bool Dumpstate::IsUserConsentDenied() const {
3484 return ds.consent_callback_ != nullptr &&
3485 ds.consent_callback_->getResult() == UserConsentResult::DENIED;
3486}
3487
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01003488bool Dumpstate::CalledByApi() const {
3489 return ds.options_->bugreport_fd.get() != -1 ? true : false;
3490}
3491
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003492void Dumpstate::CleanupTmpFiles() {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003493 android::os::UnlinkAndLogOnError(tmp_path_);
3494 android::os::UnlinkAndLogOnError(screenshot_path_);
3495 android::os::UnlinkAndLogOnError(path_);
Gavin Corkery789d7a52021-02-24 23:52:35 +00003496 if (dump_traces_path != nullptr) {
3497 android::os::UnlinkAndLogOnError(dump_traces_path);
3498 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003499}
3500
Rhed Jao5377d792020-07-16 17:37:39 +08003501void Dumpstate::EnableParallelRunIfNeeded() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003502 if (!PropertiesHelper::IsParallelRun()) {
Rhed Jao5377d792020-07-16 17:37:39 +08003503 return;
3504 }
3505 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003506 zip_entry_tasks_ = std::make_unique<TaskQueue>();
Rhed Jao5377d792020-07-16 17:37:39 +08003507}
3508
3509void Dumpstate::ShutdownDumpPool() {
3510 if (dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08003511 dump_pool_.reset();
Rhed Jao5377d792020-07-16 17:37:39 +08003512 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003513 if (zip_entry_tasks_) {
3514 zip_entry_tasks_->run(/* do_cancel = */true);
3515 zip_entry_tasks_ = nullptr;
3516 }
3517}
3518
3519void Dumpstate::EnqueueAddZipEntryAndCleanupIfNeeded(const std::string& entry_name,
3520 const std::string& entry_path) {
3521 auto func_add_zip_entry_and_cleanup = [=](bool task_cancelled) {
3522 if (!task_cancelled) {
3523 AddZipEntry(entry_name, entry_path);
3524 }
3525 android::os::UnlinkAndLogOnError(entry_path);
3526 };
3527 if (zip_entry_tasks_) {
3528 // Enqueues AddZipEntryAndCleanup function if the parallel run is enabled.
3529 zip_entry_tasks_->add(func_add_zip_entry_and_cleanup, _1);
3530 } else {
3531 // Invokes AddZipEntryAndCleanup immediately
3532 std::invoke(func_add_zip_entry_and_cleanup, /* task_cancelled = */false);
3533 }
Rhed Jao5377d792020-07-16 17:37:39 +08003534}
3535
Nandana Duttd2f5f082019-01-18 17:13:52 +00003536Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
3537 MYLOGD("User denied consent; deleting files and returning\n");
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003538 CleanupTmpFiles();
Nandana Duttd2f5f082019-01-18 17:13:52 +00003539 return USER_CONSENT_DENIED;
3540}
3541
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003542Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented(int32_t calling_uid) {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003543 // If the caller has asked to copy the bugreport over to their directory, we need explicit
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003544 // user consent (unless the caller is Shell).
3545 UserConsentResult consent_result;
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003546 if (multiuser_get_app_id(calling_uid) == AID_SHELL) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003547 consent_result = UserConsentResult::APPROVED;
3548 } else {
3549 consent_result = consent_callback_->getResult();
3550 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003551 if (consent_result == UserConsentResult::UNAVAILABLE) {
3552 // User has not responded yet.
3553 uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
Hunter Knepshield70610fa2020-01-03 15:27:33 -08003554 // Telephony is a fast report type, particularly on user builds where information may be
3555 // more aggressively limited. To give the user time to read the consent dialog, increase the
3556 // timeout.
3557 uint64_t timeout_ms = options_->telephony_only ? TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS
3558 : USER_CONSENT_TIMEOUT_MS;
3559 if (elapsed_ms < timeout_ms) {
3560 uint delay_seconds = (timeout_ms - elapsed_ms) / 1000;
Nandana Duttd2f5f082019-01-18 17:13:52 +00003561 MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
3562 sleep(delay_seconds);
3563 }
3564 consent_result = consent_callback_->getResult();
3565 }
3566 if (consent_result == UserConsentResult::DENIED) {
3567 // User has explicitly denied sharing with the app. To be safe delete the
3568 // internal bugreport & tmp files.
3569 return HandleUserConsentDenied();
3570 }
3571 if (consent_result == UserConsentResult::APPROVED) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00003572 bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
3573 if (copy_succeeded) {
3574 android::os::UnlinkAndLogOnError(path_);
Abhijeet Kaur9ce94672020-04-01 17:22:36 +01003575 if (options_->do_screenshot &&
3576 options_->screenshot_fd.get() != -1 &&
3577 !options_->is_screenshot_copied) {
3578 copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
3579 options_->screenshot_fd.get());
3580 options_->is_screenshot_copied = copy_succeeded;
3581 if (copy_succeeded) {
3582 android::os::UnlinkAndLogOnError(screenshot_path_);
3583 }
3584 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003585 }
3586 return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
3587 } else if (consent_result == UserConsentResult::UNAVAILABLE) {
3588 // consent_result is still UNAVAILABLE. The user has likely not responded yet.
3589 // Since we do not have user consent to share the bugreport it does not get
3590 // copied over to the calling app but remains in the internal directory from
3591 // where the user can manually pull it.
Paul Changce644212021-05-11 16:06:45 +08003592 std::string final_path = GetPath(".zip");
3593 bool copy_succeeded = android::os::CopyFileToFile(path_, final_path);
3594 if (copy_succeeded) {
3595 android::os::UnlinkAndLogOnError(path_);
3596 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003597 return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
3598 }
3599 // Unknown result; must be a programming error.
3600 MYLOGE("Unknown user consent result:%d\n", consent_result);
3601 return Dumpstate::RunStatus::ERROR;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003602}
3603
Nandana Duttf02564e2019-02-15 15:24:24 +00003604Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003605 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
3606 Dumpstate::RunStatus status = options->Initialize(argc, argv);
3607 if (status == Dumpstate::RunStatus::OK) {
Nandana Duttf02564e2019-02-15 15:24:24 +00003608 SetOptions(std::move(options));
Nandana Duttd2f5f082019-01-18 17:13:52 +00003609 // When directly running dumpstate binary, the output is not expected to be written
3610 // to any external file descriptor.
Nandana Duttf02564e2019-02-15 15:24:24 +00003611 assert(options_->bugreport_fd.get() == -1);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003612
3613 // calling_uid and calling_package are for user consent to share the bugreport with
Abhijeet Kaura407fb82020-03-27 12:51:12 +00003614 // an app; they are irrelevant here because bugreport is triggered via command line.
3615 // Update Last ID before calling Run().
3616 Initialize();
Nikhil Kumarb70622a2023-06-15 15:37:19 +01003617 status = Run(0 /* calling_uid */, "" /* calling_package */);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003618 }
Nandana Duttf02564e2019-02-15 15:24:24 +00003619 return status;
3620}
3621
3622/* Main entry point for dumpstate binary. */
3623int run_main(int argc, char* argv[]) {
3624 Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003625
3626 switch (status) {
3627 case Dumpstate::RunStatus::OK:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003628 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003629 case Dumpstate::RunStatus::HELP:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003630 ShowUsage();
3631 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003632 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003633 fprintf(stderr, "Invalid combination of args\n");
3634 ShowUsage();
3635 exit(1);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003636 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003637 FALLTHROUGH_INTENDED;
3638 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3639 FALLTHROUGH_INTENDED;
3640 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003641 exit(2);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003642 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003643}
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003644
3645// TODO(111441001): Default DumpOptions to sensible values.
3646Dumpstate::Dumpstate(const std::string& version)
3647 : pid_(getpid()),
3648 options_(new Dumpstate::DumpOptions()),
Nandana Dutt402a8392019-06-14 14:25:13 +01003649 last_reported_percent_progress_(0),
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003650 version_(version),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003651 now_(time(nullptr)),
3652 open_socket_fn_(open_socket) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003653}
3654
3655Dumpstate& Dumpstate::GetInstance() {
3656 static Dumpstate singleton_(android::base::GetProperty("dumpstate.version", VERSION_CURRENT));
3657 return singleton_;
3658}
3659
Rhed Jao5377d792020-07-16 17:37:39 +08003660DurationReporter::DurationReporter(const std::string& title, bool logcat_only, bool verbose,
3661 int duration_fd) : title_(title), logcat_only_(logcat_only), verbose_(verbose),
3662 duration_fd_(duration_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003663 if (!title_.empty()) {
3664 started_ = Nanotime();
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003665 if (title_.find("SHOW MAP") == std::string::npos) {
3666 ATRACE_ASYNC_BEGIN(title_.c_str(), 0);
3667 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003668 }
3669}
3670
3671DurationReporter::~DurationReporter() {
3672 if (!title_.empty()) {
3673 float elapsed = (float)(Nanotime() - started_) / NANOS_PER_SEC;
chenqiwuaf8b2d92019-12-12 18:53:51 +08003674 if (elapsed >= .5f || verbose_) {
3675 MYLOGD("Duration of '%s': %.2fs\n", title_.c_str(), elapsed);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003676 }
chenqiwuaf8b2d92019-12-12 18:53:51 +08003677 if (!logcat_only_) {
3678 // Use "Yoda grammar" to make it easier to grep|sort sections.
Rhed Jao5377d792020-07-16 17:37:39 +08003679 dprintf(duration_fd_, "------ %.3fs was the duration of '%s' ------\n",
3680 elapsed, title_.c_str());
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003681 }
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003682 if (title_.find("SHOW MAP") == std::string::npos) {
3683 ATRACE_ASYNC_END(title_.c_str(), 0);
3684 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003685 }
3686}
3687
3688const int32_t Progress::kDefaultMax = 5000;
3689
3690Progress::Progress(const std::string& path) : Progress(Progress::kDefaultMax, 1.1, path) {
3691}
3692
3693Progress::Progress(int32_t initial_max, int32_t progress, float growth_factor)
3694 : Progress(initial_max, growth_factor, "") {
3695 progress_ = progress;
3696}
3697
3698Progress::Progress(int32_t initial_max, float growth_factor, const std::string& path)
3699 : initial_max_(initial_max),
3700 progress_(0),
3701 max_(initial_max),
3702 growth_factor_(growth_factor),
3703 n_runs_(0),
3704 average_max_(0),
3705 path_(path) {
3706 if (!path_.empty()) {
3707 Load();
3708 }
3709}
3710
3711void Progress::Load() {
3712 MYLOGD("Loading stats from %s\n", path_.c_str());
3713 std::string content;
3714 if (!android::base::ReadFileToString(path_, &content)) {
3715 MYLOGI("Could not read stats from %s; using max of %d\n", path_.c_str(), max_);
3716 return;
3717 }
3718 if (content.empty()) {
3719 MYLOGE("No stats (empty file) on %s; using max of %d\n", path_.c_str(), max_);
3720 return;
3721 }
3722 std::vector<std::string> lines = android::base::Split(content, "\n");
3723
3724 if (lines.size() < 1) {
3725 MYLOGE("Invalid stats on file %s: not enough lines (%d). Using max of %d\n", path_.c_str(),
3726 (int)lines.size(), max_);
3727 return;
3728 }
3729 char* ptr;
3730 n_runs_ = strtol(lines[0].c_str(), &ptr, 10);
3731 average_max_ = strtol(ptr, nullptr, 10);
3732 if (n_runs_ <= 0 || average_max_ <= 0 || n_runs_ > STATS_MAX_N_RUNS ||
3733 average_max_ > STATS_MAX_AVERAGE) {
3734 MYLOGE("Invalid stats line on file %s: %s\n", path_.c_str(), lines[0].c_str());
3735 initial_max_ = Progress::kDefaultMax;
3736 } else {
3737 initial_max_ = average_max_;
3738 }
3739 max_ = initial_max_;
3740
3741 MYLOGI("Average max progress: %d in %d runs; estimated max: %d\n", average_max_, n_runs_, max_);
3742}
3743
3744void Progress::Save() {
3745 int32_t total = n_runs_ * average_max_ + progress_;
3746 int32_t runs = n_runs_ + 1;
3747 int32_t average = floor(((float)total) / runs);
3748 MYLOGI("Saving stats (total=%d, runs=%d, average=%d) on %s\n", total, runs, average,
3749 path_.c_str());
3750 if (path_.empty()) {
3751 return;
3752 }
3753
3754 std::string content = android::base::StringPrintf("%d %d\n", runs, average);
3755 if (!android::base::WriteStringToFile(content, path_)) {
3756 MYLOGE("Could not save stats on %s\n", path_.c_str());
3757 }
3758}
3759
3760int32_t Progress::Get() const {
3761 return progress_;
3762}
3763
3764bool Progress::Inc(int32_t delta_sec) {
3765 bool changed = false;
3766 if (delta_sec >= 0) {
3767 progress_ += delta_sec;
3768 if (progress_ > max_) {
3769 int32_t old_max = max_;
3770 max_ = floor((float)progress_ * growth_factor_);
3771 MYLOGD("Adjusting max progress from %d to %d\n", old_max, max_);
3772 changed = true;
3773 }
3774 }
3775 return changed;
3776}
3777
3778int32_t Progress::GetMax() const {
3779 return max_;
3780}
3781
3782int32_t Progress::GetInitialMax() const {
3783 return initial_max_;
3784}
3785
3786void Progress::Dump(int fd, const std::string& prefix) const {
3787 const char* pr = prefix.c_str();
3788 dprintf(fd, "%sprogress: %d\n", pr, progress_);
3789 dprintf(fd, "%smax: %d\n", pr, max_);
3790 dprintf(fd, "%sinitial_max: %d\n", pr, initial_max_);
3791 dprintf(fd, "%sgrowth_factor: %0.2f\n", pr, growth_factor_);
3792 dprintf(fd, "%spath: %s\n", pr, path_.c_str());
3793 dprintf(fd, "%sn_runs: %d\n", pr, n_runs_);
3794 dprintf(fd, "%saverage_max: %d\n", pr, average_max_);
3795}
3796
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003797std::string Dumpstate::GetPath(const std::string& suffix) const {
3798 return GetPath(bugreport_internal_dir_, suffix);
3799}
3800
3801std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
3802 return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
3803 name_.c_str(), suffix.c_str());
3804}
3805
3806void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
3807 progress_ = std::move(progress);
3808}
3809
3810void for_each_userid(void (*func)(int), const char *header) {
3811 std::string title = header == nullptr ? "for_each_userid" : android::base::StringPrintf(
3812 "for_each_userid(%s)", header);
3813 DurationReporter duration_reporter(title);
3814 if (PropertiesHelper::IsDryRun()) return;
3815
3816 DIR *d;
3817 struct dirent *de;
3818
3819 if (header) printf("\n------ %s ------\n", header);
3820 func(0);
3821
3822 if (!(d = opendir("/data/system/users"))) {
3823 printf("Failed to open /data/system/users (%s)\n", strerror(errno));
3824 return;
3825 }
3826
3827 while ((de = readdir(d))) {
3828 int userid;
3829 if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
3830 continue;
3831 }
3832 func(userid);
3833 }
3834
3835 closedir(d);
3836}
3837
3838static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
3839 DIR *d;
3840 struct dirent *de;
3841
3842 if (!(d = opendir("/proc"))) {
3843 printf("Failed to open /proc (%s)\n", strerror(errno));
3844 return;
3845 }
3846
3847 if (header) printf("\n------ %s ------\n", header);
3848 while ((de = readdir(d))) {
3849 if (ds.IsUserConsentDenied()) {
3850 MYLOGE(
3851 "Returning early because user denied consent to share bugreport with calling app.");
3852 closedir(d);
3853 return;
3854 }
3855 int pid;
3856 int fd;
3857 char cmdpath[255];
3858 char cmdline[255];
3859
3860 if (!(pid = atoi(de->d_name))) {
3861 continue;
3862 }
3863
3864 memset(cmdline, 0, sizeof(cmdline));
3865
3866 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
3867 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3868 TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
3869 close(fd);
3870 if (cmdline[0]) {
3871 helper(pid, cmdline, arg);
3872 continue;
3873 }
3874 }
3875
3876 // if no cmdline, a kernel thread has comm
3877 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
3878 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3879 TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
3880 close(fd);
3881 if (cmdline[1]) {
3882 cmdline[0] = '[';
3883 size_t len = strcspn(cmdline, "\f\b\r\n");
3884 cmdline[len] = ']';
3885 cmdline[len+1] = '\0';
3886 }
3887 }
3888 if (!cmdline[0]) {
3889 strcpy(cmdline, "N/A");
3890 }
3891 helper(pid, cmdline, arg);
3892 }
3893
3894 closedir(d);
3895}
3896
3897static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
3898 for_each_pid_func *func = (for_each_pid_func*) arg;
3899 func(pid, cmdline);
3900}
3901
3902void for_each_pid(for_each_pid_func func, const char *header) {
3903 std::string title = header == nullptr ? "for_each_pid"
3904 : android::base::StringPrintf("for_each_pid(%s)", header);
3905 DurationReporter duration_reporter(title);
3906 if (PropertiesHelper::IsDryRun()) return;
3907
3908 __for_each_pid(for_each_pid_helper, header, (void *) func);
3909}
3910
3911static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
3912 DIR *d;
3913 struct dirent *de;
3914 char taskpath[255];
3915 for_each_tid_func *func = (for_each_tid_func *) arg;
3916
3917 snprintf(taskpath, sizeof(taskpath), "/proc/%d/task", pid);
3918
3919 if (!(d = opendir(taskpath))) {
3920 printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
3921 return;
3922 }
3923
3924 func(pid, pid, cmdline);
3925
3926 while ((de = readdir(d))) {
3927 if (ds.IsUserConsentDenied()) {
3928 MYLOGE(
3929 "Returning early because user denied consent to share bugreport with calling app.");
3930 closedir(d);
3931 return;
3932 }
3933 int tid;
3934 int fd;
3935 char commpath[255];
3936 char comm[255];
3937
3938 if (!(tid = atoi(de->d_name))) {
3939 continue;
3940 }
3941
3942 if (tid == pid)
3943 continue;
3944
3945 snprintf(commpath, sizeof(commpath), "/proc/%d/comm", tid);
3946 memset(comm, 0, sizeof(comm));
3947 if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
3948 strcpy(comm, "N/A");
3949 } else {
3950 char *c;
3951 TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
3952 close(fd);
3953
3954 c = strrchr(comm, '\n');
3955 if (c) {
3956 *c = '\0';
3957 }
3958 }
3959 func(pid, tid, comm);
3960 }
3961
3962 closedir(d);
3963}
3964
3965void for_each_tid(for_each_tid_func func, const char *header) {
3966 std::string title = header == nullptr ? "for_each_tid"
3967 : android::base::StringPrintf("for_each_tid(%s)", header);
3968 DurationReporter duration_reporter(title);
3969
3970 if (PropertiesHelper::IsDryRun()) return;
3971
3972 __for_each_pid(for_each_tid_helper, header, (void *) func);
3973}
3974
3975void show_wchan(int pid, int tid, const char *name) {
3976 if (PropertiesHelper::IsDryRun()) return;
3977
3978 char path[255];
3979 char buffer[255];
3980 int fd, ret, save_errno;
3981 char name_buffer[255];
3982
3983 memset(buffer, 0, sizeof(buffer));
3984
3985 snprintf(path, sizeof(path), "/proc/%d/wchan", tid);
3986 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
3987 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
3988 return;
3989 }
3990
3991 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3992 save_errno = errno;
3993 close(fd);
3994
3995 if (ret < 0) {
3996 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
3997 return;
3998 }
3999
4000 snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
4001 pid == tid ? 0 : 3, "", name);
4002
4003 printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
4004
4005 return;
4006}
4007
4008// print time in centiseconds
4009static void snprcent(char *buffer, size_t len, size_t spc,
4010 unsigned long long time) {
4011 static long hz; // cache discovered hz
4012
4013 if (hz <= 0) {
4014 hz = sysconf(_SC_CLK_TCK);
4015 if (hz <= 0) {
4016 hz = 1000;
4017 }
4018 }
4019
4020 // convert to centiseconds
4021 time = (time * 100 + (hz / 2)) / hz;
4022
4023 char str[16];
4024
4025 snprintf(str, sizeof(str), " %llu.%02u",
4026 time / 100, (unsigned)(time % 100));
4027 size_t offset = strlen(buffer);
4028 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
4029 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
4030}
4031
4032// print permille as a percent
4033static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
4034 char str[16];
4035
4036 snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
4037 size_t offset = strlen(buffer);
4038 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
4039 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
4040}
4041
4042void show_showtime(int pid, const char *name) {
4043 if (PropertiesHelper::IsDryRun()) return;
4044
4045 char path[255];
4046 char buffer[1023];
4047 int fd, ret, save_errno;
4048
4049 memset(buffer, 0, sizeof(buffer));
4050
4051 snprintf(path, sizeof(path), "/proc/%d/stat", pid);
4052 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
4053 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
4054 return;
4055 }
4056
4057 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
4058 save_errno = errno;
4059 close(fd);
4060
4061 if (ret < 0) {
4062 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
4063 return;
4064 }
4065
4066 // field 14 is utime
4067 // field 15 is stime
4068 // field 42 is iotime
4069 unsigned long long utime = 0, stime = 0, iotime = 0;
4070 if (sscanf(buffer,
4071 "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
4072 "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
4073 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
4074 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
4075 &utime, &stime, &iotime) != 3) {
4076 return;
4077 }
4078
4079 unsigned long long total = utime + stime;
4080 if (!total) {
4081 return;
4082 }
4083
4084 unsigned permille = (iotime * 1000 + (total / 2)) / total;
4085 if (permille > 1000) {
4086 permille = 1000;
4087 }
4088
4089 // try to beautify and stabilize columns at <80 characters
4090 snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
4091 if ((name[0] != '[') || utime) {
4092 snprcent(buffer, sizeof(buffer), 57, utime);
4093 }
4094 snprcent(buffer, sizeof(buffer), 65, stime);
4095 if ((name[0] != '[') || iotime) {
4096 snprcent(buffer, sizeof(buffer), 73, iotime);
4097 }
4098 if (iotime) {
4099 snprdec(buffer, sizeof(buffer), 79, permille);
4100 }
4101 puts(buffer); // adds a trailing newline
4102
4103 return;
4104}
4105
4106void do_dmesg() {
4107 const char *title = "KERNEL LOG (dmesg)";
4108 DurationReporter duration_reporter(title);
4109 printf("------ %s ------\n", title);
4110
4111 if (PropertiesHelper::IsDryRun()) return;
4112
4113 /* Get size of kernel buffer */
4114 int size = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
4115 if (size <= 0) {
4116 printf("Unexpected klogctl return value: %d\n\n", size);
4117 return;
4118 }
4119 char *buf = (char *) malloc(size + 1);
4120 if (buf == nullptr) {
4121 printf("memory allocation failed\n\n");
4122 return;
4123 }
4124 int retval = klogctl(KLOG_READ_ALL, buf, size);
4125 if (retval < 0) {
4126 printf("klogctl failure\n\n");
4127 free(buf);
4128 return;
4129 }
4130 buf[retval] = '\0';
4131 printf("%s\n\n", buf);
4132 free(buf);
4133 return;
4134}
4135
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004136int Dumpstate::DumpFile(const std::string& title, const std::string& path) {
4137 DurationReporter duration_reporter(title);
4138
4139 int status = DumpFileToFd(STDOUT_FILENO, title, path);
4140
4141 UpdateProgress(WEIGHT_FILE);
4142
4143 return status;
4144}
4145
4146int read_file_as_long(const char *path, long int *output) {
luoqiangwei15fcf2022024-03-07 15:29:20 +08004147 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
4148 if (fd.get() < 0) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004149 int err = errno;
4150 MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
4151 return -1;
4152 }
4153 char buffer[50];
luoqiangwei15fcf2022024-03-07 15:29:20 +08004154 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer, sizeof(buffer)));
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004155 if (bytes_read == -1) {
4156 MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
4157 return -2;
4158 }
4159 if (bytes_read == 0) {
4160 MYLOGE("File %s is empty\n", path);
4161 return -3;
4162 }
4163 *output = atoi(buffer);
4164 return 0;
4165}
4166
4167/* calls skip to gate calling dump_from_fd recursively
4168 * in the specified directory. dump_from_fd defaults to
4169 * dump_file_from_fd above when set to NULL. skip defaults
4170 * to false when set to NULL. dump_from_fd will always be
4171 * called with title NULL.
4172 */
4173int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
4174 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4175 DurationReporter duration_reporter(title);
4176 DIR *dirp;
4177 struct dirent *d;
4178 char *newpath = nullptr;
4179 const char *slash = "/";
4180 int retval = 0;
4181
4182 if (!title.empty()) {
4183 printf("------ %s (%s) ------\n", title.c_str(), dir);
4184 }
4185 if (PropertiesHelper::IsDryRun()) return 0;
4186
4187 if (dir[strlen(dir) - 1] == '/') {
4188 ++slash;
4189 }
4190 dirp = opendir(dir);
4191 if (dirp == nullptr) {
4192 retval = -errno;
4193 MYLOGE("%s: %s\n", dir, strerror(errno));
4194 return retval;
4195 }
4196
4197 if (!dump_from_fd) {
4198 dump_from_fd = dump_file_from_fd;
4199 }
4200 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4201 if ((d->d_name[0] == '.')
4202 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4203 || (d->d_name[1] == '\0'))) {
4204 continue;
4205 }
4206 asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
4207 (d->d_type == DT_DIR) ? "/" : "");
4208 if (!newpath) {
4209 retval = -errno;
4210 continue;
4211 }
4212 if (skip && (*skip)(newpath)) {
4213 continue;
4214 }
4215 if (d->d_type == DT_DIR) {
4216 int ret = dump_files("", newpath, skip, dump_from_fd);
4217 if (ret < 0) {
4218 retval = ret;
4219 }
4220 continue;
4221 }
4222 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
4223 if (fd.get() < 0) {
4224 retval = -1;
4225 printf("*** %s: %s\n", newpath, strerror(errno));
4226 continue;
4227 }
4228 (*dump_from_fd)(nullptr, newpath, fd.get());
4229 }
4230 closedir(dirp);
4231 if (!title.empty()) {
4232 printf("\n");
4233 }
4234 return retval;
4235}
4236
4237/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
4238 * it's possible to avoid issues where opening the file itself can get
4239 * stuck.
4240 */
4241int dump_file_from_fd(const char *title, const char *path, int fd) {
4242 if (PropertiesHelper::IsDryRun()) return 0;
4243
4244 int flags = fcntl(fd, F_GETFL);
4245 if (flags == -1) {
4246 printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
4247 return -1;
4248 } else if (!(flags & O_NONBLOCK)) {
4249 printf("*** %s: fd must have O_NONBLOCK set.\n", path);
4250 return -1;
4251 }
4252 return DumpFileFromFdToFd(title, path, fd, STDOUT_FILENO, PropertiesHelper::IsDryRun());
4253}
4254
4255int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004256 const CommandOptions& options, bool verbose_duration, int out_fd) {
4257 DurationReporter duration_reporter(title, false /* logcat_only */,
4258 verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004259
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004260 int status = RunCommandToFd(out_fd, title, full_command, options);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004261
4262 /* TODO: for now we're simplifying the progress calculation by using the
4263 * timeout as the weight. It's a good approximation for most cases, except when calling dumpsys,
4264 * where its weight should be much higher proportionally to its timeout.
4265 * Ideally, it should use a options.EstimatedDuration() instead...*/
4266 UpdateProgress(options.Timeout());
4267
4268 return status;
4269}
4270
4271void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
Rhed Jaoe017f982020-07-21 17:58:41 +08004272 const CommandOptions& options, long dumpsysTimeoutMs, int out_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004273 long timeout_ms = dumpsysTimeoutMs > 0 ? dumpsysTimeoutMs : options.TimeoutInMs();
4274 std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-T", std::to_string(timeout_ms)};
4275 dumpsys.insert(dumpsys.end(), dumpsys_args.begin(), dumpsys_args.end());
Rhed Jaoe017f982020-07-21 17:58:41 +08004276 RunCommand(title, dumpsys, options, false, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004277}
4278
Dieter Hsu105ad0c2020-09-29 15:23:33 +08004279static int open_socket(const char* service) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004280 int s = android_get_control_socket(service);
4281 if (s < 0) {
4282 MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
4283 return -1;
4284 }
4285 fcntl(s, F_SETFD, FD_CLOEXEC);
4286
4287 // Set backlog to 0 to make sure that queue size will be minimum.
4288 // In Linux, because the minimum queue will be 1, connect() will be blocked
4289 // if the other clients already called connect() and the connection request was not accepted.
4290 if (listen(s, 0) < 0) {
4291 MYLOGE("listen(control socket): %s\n", strerror(errno));
4292 return -1;
4293 }
4294
4295 struct sockaddr addr;
4296 socklen_t alen = sizeof(addr);
Abhijeet Kaur2113cae2019-09-13 09:24:15 +01004297 int fd = accept4(s, &addr, &alen, SOCK_CLOEXEC);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004298
4299 // Close socket just after accept(), to make sure that connect() by client will get error
4300 // when the socket is used by the other services.
4301 // There is still a race condition possibility between accept and close, but there is no way
4302 // to close-on-accept atomically.
4303 // See detail; b/123306389#comment25
4304 close(s);
4305
4306 if (fd < 0) {
4307 MYLOGE("accept(control socket): %s\n", strerror(errno));
4308 return -1;
4309 }
4310
4311 return fd;
4312}
4313
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004314// TODO: should call is_valid_output_file and/or be merged into it.
4315void create_parent_dirs(const char *path) {
4316 char *chp = const_cast<char *> (path);
4317
4318 /* skip initial slash */
4319 if (chp[0] == '/')
4320 chp++;
4321
4322 /* create leading directories, if necessary */
4323 struct stat dir_stat;
4324 while (chp && chp[0]) {
4325 chp = strchr(chp, '/');
4326 if (chp) {
4327 *chp = 0;
4328 if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
4329 MYLOGI("Creating directory %s\n", path);
4330 if (mkdir(path, 0770)) { /* drwxrwx--- */
4331 MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
4332 } else if (chown(path, AID_SHELL, AID_SHELL)) {
4333 MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
4334 }
4335 }
4336 *chp++ = '/';
4337 }
4338 }
4339}
4340
4341bool _redirect_to_file(FILE* redirect, char* path, int truncate_flag) {
4342 create_parent_dirs(path);
4343
4344 int fd = TEMP_FAILURE_RETRY(open(path,
4345 O_WRONLY | O_CREAT | truncate_flag | O_CLOEXEC | O_NOFOLLOW,
4346 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
4347 if (fd < 0) {
4348 MYLOGE("%s: %s\n", path, strerror(errno));
4349 return false;
4350 }
4351
4352 TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
4353 close(fd);
4354 return true;
4355}
4356
4357bool redirect_to_file(FILE* redirect, char* path) {
4358 return _redirect_to_file(redirect, path, O_TRUNC);
4359}
4360
4361bool redirect_to_existing_file(FILE* redirect, char* path) {
4362 return _redirect_to_file(redirect, path, O_APPEND);
4363}
4364
4365void dump_route_tables() {
4366 DurationReporter duration_reporter("DUMP ROUTE TABLES");
4367 if (PropertiesHelper::IsDryRun()) return;
4368 const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
4369 ds.DumpFile("RT_TABLES", RT_TABLES_PATH);
4370 FILE* fp = fopen(RT_TABLES_PATH, "re");
4371 if (!fp) {
4372 printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
4373 return;
4374 }
4375 char table[16];
4376 // Each line has an integer (the table number), a space, and a string (the table name). We only
4377 // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
4378 // Add a fixed max limit so this doesn't go awry.
4379 for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
4380 RunCommand("ROUTE TABLE IPv4", {"ip", "-4", "route", "show", "table", table});
4381 RunCommand("ROUTE TABLE IPv6", {"ip", "-6", "route", "show", "table", table});
4382 }
4383 fclose(fp);
4384}
4385
Li Li830179f2022-01-04 12:53:29 -08004386void dump_frozen_cgroupfs(const char *dir, int level,
4387 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4388 DIR *dirp;
4389 struct dirent *d;
4390 char *newpath = nullptr;
4391
4392 dirp = opendir(dir);
4393 if (dirp == nullptr) {
4394 MYLOGE("%s: %s\n", dir, strerror(errno));
4395 return;
4396 }
4397
4398 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4399 if ((d->d_name[0] == '.')
4400 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4401 || (d->d_name[1] == '\0'))) {
4402 continue;
4403 }
4404 if (d->d_type == DT_DIR) {
4405 asprintf(&newpath, "%s/%s/", dir, d->d_name);
4406 if (!newpath) {
4407 continue;
4408 }
4409 if (level == 0 && !strncmp(d->d_name, "uid_", 4)) {
4410 dump_frozen_cgroupfs(newpath, 1, dump_from_fd);
4411 } else if (level == 1 && !strncmp(d->d_name, "pid_", 4)) {
4412 char *freezer = nullptr;
4413 asprintf(&freezer, "%s/%s", newpath, "cgroup.freeze");
4414 if (freezer) {
4415 FILE* fp = fopen(freezer, "r");
4416 if (fp != NULL) {
4417 int frozen;
4418 fscanf(fp, "%d", &frozen);
4419 if (frozen > 0) {
4420 dump_files("", newpath, skip_none, dump_from_fd);
4421 }
4422 fclose(fp);
4423 }
4424 free(freezer);
4425 }
4426 }
4427 }
4428 }
4429 closedir(dirp);
4430}
4431
4432void dump_frozen_cgroupfs() {
Li Li830179f2022-01-04 12:53:29 -08004433 MYLOGD("Adding frozen processes from %s\n", CGROUPFS_DIR);
4434 DurationReporter duration_reporter("FROZEN CGROUPFS");
4435 if (PropertiesHelper::IsDryRun()) return;
4436 dump_frozen_cgroupfs(CGROUPFS_DIR, 0, _add_file_from_fd);
4437}
4438
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004439void Dumpstate::UpdateProgress(int32_t delta_sec) {
4440 if (progress_ == nullptr) {
4441 MYLOGE("UpdateProgress: progress_ not set\n");
4442 return;
4443 }
Rhed Jaobf63d8a2020-07-21 15:42:55 +08004444 // This function updates progress related members of the dumpstate and reports
4445 // progress percentage to the bugreport client. Since it could be called by
4446 // different dump tasks at the same time if the parallel run is enabled, a
4447 // mutex lock is necessary here to synchronize the call.
4448 std::lock_guard<std::recursive_mutex> lock(mutex_);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004449
4450 // Always update progess so stats can be tuned...
Nandana Dutt402a8392019-06-14 14:25:13 +01004451 progress_->Inc(delta_sec);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004452
4453 // ...but only notifiy listeners when necessary.
4454 if (!options_->do_progress_updates) return;
4455
4456 int progress = progress_->Get();
4457 int max = progress_->GetMax();
Nandana Dutt402a8392019-06-14 14:25:13 +01004458 int percent = 100 * progress / max;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004459
Nandana Dutt402a8392019-06-14 14:25:13 +01004460 if (last_reported_percent_progress_ > 0 && percent <= last_reported_percent_progress_) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004461 return;
4462 }
Nandana Dutt402a8392019-06-14 14:25:13 +01004463 last_reported_percent_progress_ = percent;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004464
4465 if (control_socket_fd_ >= 0) {
4466 dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
4467 fsync(control_socket_fd_);
4468 }
4469
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004470 if (listener_ != nullptr) {
Nandana Dutt235c6672019-11-14 15:22:32 +00004471 if (percent % 10 == 0) {
4472 // We don't want to spam logcat, so only log multiples of 10.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004473 MYLOGD("Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004474 } else {
4475 // stderr is ignored on normal invocations, but useful when calling
4476 // /system/bin/dumpstate directly for debuggging.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004477 fprintf(stderr, "Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004478 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004479
4480 listener_->onProgress(percent);
4481 }
4482}
4483
4484void Dumpstate::TakeScreenshot(const std::string& path) {
4485 const std::string& real_path = path.empty() ? screenshot_path_ : path;
4486 int status =
4487 RunCommand("", {"/system/bin/screencap", "-p", real_path},
4488 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
4489 if (status == 0) {
4490 MYLOGD("Screenshot saved on %s\n", real_path.c_str());
4491 } else {
4492 MYLOGE("Failed to take screenshot on %s\n", real_path.c_str());
4493 }
Paul Chang0d2aad72020-02-13 20:04:03 +08004494 if (listener_ != nullptr) {
4495 // Show a visual indication to indicate screenshot is taken via
4496 // IDumpstateListener.onScreenshotTaken()
4497 listener_->onScreenshotTaken(status == 0);
4498 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004499}
4500
4501bool is_dir(const char* pathname) {
4502 struct stat info;
4503 if (stat(pathname, &info) == -1) {
4504 return false;
4505 }
4506 return S_ISDIR(info.st_mode);
4507}
4508
4509time_t get_mtime(int fd, time_t default_mtime) {
4510 struct stat info;
4511 if (fstat(fd, &info) == -1) {
4512 return default_mtime;
4513 }
4514 return info.st_mtime;
4515}