blob: c501921399625d58acaf77648133feeab32902a0 [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>
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +000062#include <android_app_admin_flags.h>
Felipe Leme96c2bbb2016-09-26 09:21:21 -070063#include <android-base/file.h>
64#include <android-base/properties.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070065#include <android-base/scopeguard.h>
Elliott Hughes9dc117c2015-12-07 14:21:50 -080066#include <android-base/stringprintf.h>
Naveen Kalla058e1e82016-10-19 21:38:44 -070067#include <android-base/strings.h>
Andreas Gampeaff68432016-07-18 18:01:27 -070068#include <android-base/unique_fd.h>
Kedar Chitnis9fd8c052021-11-16 09:09:22 +000069#include <android/binder_manager.h>
70#include <android/binder_process.h>
Nikita Ioffea325a572019-05-16 19:49:47 +010071#include <android/content/pm/IPackageManagerNative.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080072#include <android/hardware/dumpstate/1.0/IDumpstateDevice.h>
Hunter Knepshield8540faf2020-02-04 19:47:20 -080073#include <android/hardware/dumpstate/1.1/IDumpstateDevice.h>
74#include <android/hardware/dumpstate/1.1/types.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080075#include <android/hidl/manager/1.0/IServiceManager.h>
Nandana Duttd2f5f082019-01-18 17:13:52 +000076#include <android/os/IIncidentCompanion.h>
Nikita Ioffea325a572019-05-16 19:49:47 +010077#include <binder/IServiceManager.h>
Nikhil Kumar28ce35e2023-01-10 14:32:44 +000078#include <cutils/multiuser.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080079#include <cutils/native_handle.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070080#include <cutils/properties.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010081#include <cutils/sockets.h>
Kevin Jeon2c02e8e2022-07-07 21:45:17 +000082#include <cutils/trace.h>
Nandana Duttfaafd522019-03-11 09:23:09 +000083#include <debuggerd/client.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080084#include <dumpsys.h>
Nandana Duttfaafd522019-03-11 09:23:09 +000085#include <dumputils/dump_utils.h>
Sahana Raof35ed432019-07-12 10:47:52 +010086#include <hardware_legacy/power.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080087#include <hidl/ServiceManagement.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010088#include <log/log.h>
Tom Cherryf4472f32020-08-05 09:31:17 -070089#include <log/log_read.h>
Felipe Leme75876a22016-10-27 16:31:27 -070090#include <openssl/sha.h>
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070091#include <private/android_filesystem_config.h>
92#include <private/android_logger.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080093#include <serviceutils/PriorityDumper.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070094#include <utils/StrongPointer.h>
Devin Moore8df81bb2022-06-08 22:47:02 +000095#include <vintf/VintfObject.h>
Felipe Lemef0292972016-11-22 13:57:05 -080096#include "DumpstateInternal.h"
Felipe Leme75876a22016-10-27 16:31:27 -070097#include "DumpstateService.h"
Colin Crossf45fa6b2012-03-26 12:38:26 -070098#include "dumpstate.h"
Felipe Leme6e01fa62015-11-11 19:35:14 -080099
Kedar Chitnis9fd8c052021-11-16 09:09:22 +0000100namespace dumpstate_hal_hidl_1_0 = android::hardware::dumpstate::V1_0;
101namespace dumpstate_hal_hidl = android::hardware::dumpstate::V1_1;
102namespace dumpstate_hal_aidl = aidl::android::hardware::dumpstate;
103
Vishnu Naire97d6122018-01-18 13:58:56 -0800104using ::std::literals::chrono_literals::operator""ms;
105using ::std::literals::chrono_literals::operator""s;
Rhed Jao5377d792020-07-16 17:37:39 +0800106using ::std::placeholders::_1;
Steven Morelandcb7ef822016-11-29 13:20:37 -0800107
Felipe Leme47e9be22016-12-21 15:37:07 -0800108// TODO: remove once moved to namespace
Vishnu Naire97d6122018-01-18 13:58:56 -0800109using android::defaultServiceManager;
110using android::Dumpsys;
111using android::INVALID_OPERATION;
112using android::IServiceManager;
113using android::OK;
114using android::sp;
115using android::status_t;
116using android::String16;
117using android::String8;
118using android::TIMED_OUT;
119using android::UNKNOWN_ERROR;
120using android::Vector;
Nandana Dutt979388e2018-11-30 16:48:55 +0000121using android::base::StringPrintf;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000122using android::os::IDumpstateListener;
Felipe Leme47e9be22016-12-21 15:37:07 -0800123using android::os::dumpstate::CommandOptions;
124using android::os::dumpstate::DumpFileToFd;
Rhed Jao5377d792020-07-16 17:37:39 +0800125using android::os::dumpstate::DumpPool;
Vishnu Naire97d6122018-01-18 13:58:56 -0800126using android::os::dumpstate::PropertiesHelper;
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800127using android::os::dumpstate::TaskQueue;
Chris Morinbc223142022-02-04 14:17:11 -0800128using android::os::dumpstate::WaitForTask;
Felipe Leme47e9be22016-12-21 15:37:07 -0800129
Abhijeet Kaurcf234e82019-07-01 14:53:55 +0100130// Keep in sync with
131// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
132static const int TRACE_DUMP_TIMEOUT_MS = 10000; // 10 seconds
133
134/* Most simple commands have 10 as timeout, so 5 is a good estimate */
135static const int32_t WEIGHT_FILE = 5;
136
137// TODO: temporary variables and functions used during C++ refactoring
138static Dumpstate& ds = Dumpstate::GetInstance();
139static int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Nandana Dutt8d945c02019-08-14 13:30:07 +0100140 const CommandOptions& options = CommandOptions::DEFAULT,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800141 bool verbose_duration = false, int out_fd = STDOUT_FILENO) {
142 return ds.RunCommand(title, full_command, options, verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +0100143}
144
145// Reasonable value for max stats.
146static const int STATS_MAX_N_RUNS = 1000;
147static const long STATS_MAX_AVERAGE = 100000;
148
149CommandOptions Dumpstate::DEFAULT_DUMPSYS = CommandOptions::WithTimeout(30).Build();
150
Nandana Duttd2f5f082019-01-18 17:13:52 +0000151typedef Dumpstate::ConsentCallback::ConsentResult UserConsentResult;
152
Colin Crossf45fa6b2012-03-26 12:38:26 -0700153/* read before root is shed */
154static char cmdline_buf[16384] = "(unknown)";
Yi Kong19d5c002018-07-20 13:39:55 -0700155static const char *dump_traces_path = nullptr;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000156static const uint64_t USER_CONSENT_TIMEOUT_MS = 30 * 1000;
Hunter Knepshield70610fa2020-01-03 15:27:33 -0800157// Because telephony reports are significantly faster to collect (< 10 seconds vs. > 2 minutes),
158// it's often the case that they time out far too quickly for consent with such a hefty dialog for
159// the user to read. For telephony reports only, we increase the default timeout to 2 minutes to
160// roughly match full reports' durations.
161static const uint64_t TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS = 2 * 60 * 1000;
Colin Crossf45fa6b2012-03-26 12:38:26 -0700162
Felipe Leme1d486fe2016-10-14 18:06:47 -0700163// TODO: variables and functions below should be part of dumpstate object
164
Felipe Leme635ca312016-01-05 14:23:02 -0800165static std::set<std::string> mount_points;
166void add_mountinfo();
Felipe Leme78f2c862015-12-21 09:55:22 -0800167
Todd Poynor2a83daa2013-11-22 15:44:22 -0800168#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
Mark Salyzyn7d0a7622016-06-24 14:06:15 -0700169#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
Wei Wang509bb5d2017-06-09 14:42:12 -0700170#define BLK_DEV_SYS_DIR "/sys/block"
Todd Poynor2a83daa2013-11-22 15:44:22 -0800171
Felipe Lemee82a27d2016-01-05 13:35:44 -0800172#define RECOVERY_DIR "/cache/recovery"
Mark Salyzynd6ab0112016-03-25 12:56:39 -0700173#define RECOVERY_DATA_DIR "/data/misc/recovery"
Tianjie Xu75d53362018-04-11 16:42:28 -0700174#define UPDATE_ENGINE_LOG_DIR "/data/misc/update_engine_log"
Kelvin Zhang6eaa0f92022-09-12 09:29:19 -0700175#define UPDATE_ENGINE_PREF_DIR "/data/misc/update_engine/prefs"
Mark Salyzyn4d42dea2016-04-01 10:03:14 -0700176#define LOGPERSIST_DATA_DIR "/data/misc/logd"
Jerry Changa1df8a92020-01-02 16:03:39 +0800177#define PREREBOOT_DATA_DIR "/data/misc/prereboot"
David Brazdild2991962016-06-03 14:40:44 +0100178#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
179#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
Benedict Wong8f9d8a42019-01-03 16:19:38 -0800180#define XFRM_STAT_PROC_FILE "/proc/net/xfrm_stat"
Steven Moreland9379c462023-12-21 02:04:27 +0000181#define KERNEL_CONFIG "/proc/config.gz"
Erik Kline08165202016-05-30 11:55:44 +0900182#define WLUTIL "/vendor/xbin/wlutil"
Vishnu Nair36b4cdb2017-11-17 10:27:05 -0800183#define WMTRACE_DATA_DIR "/data/misc/wmtrace"
Yifan Hong3945e1b2019-10-29 12:59:23 -0700184#define OTA_METADATA_DIR "/metadata/ota"
Yifan Hong0efa7972020-02-03 16:45:02 -0800185#define SNAPSHOTCTL_LOG_DIR "/data/misc/snapshotctl_log"
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +0900186#define LINKERCONFIG_DIR "/linkerconfig"
Calin Juravlef84d3692020-04-28 15:31:12 -0700187#define PACKAGE_DEX_USE_LIST "/data/system/package-dex-usage.list"
Primiano Tuccifaaaafb2021-01-14 12:26:29 +0000188#define SYSTEM_TRACE_SNAPSHOT "/data/misc/perfetto-traces/bugreport/systrace.pftrace"
Li Li2eedd412021-06-30 15:11:53 -0700189#define CGROUPFS_DIR "/sys/fs/cgroup"
Mårten Kongstad60195a72022-09-20 14:14:20 +0200190#define SDK_EXT_INFO "/apex/com.android.sdkext/bin/derive_sdk"
Jeff Sharkey9df29d52023-02-06 14:26:30 -0700191#define DROPBOX_DIR "/data/system/dropbox"
Mårten Kongstad5ad813f2023-09-28 10:09:18 +0200192#define PRINT_FLAGS "/system/bin/printflags"
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700193
Narayan Kamath8f788292017-05-25 13:20:39 +0100194// TODO(narayan): Since this information has to be kept in sync
195// with tombstoned, we should just put it in a common header.
196//
197// File: system/core/debuggerd/tombstoned/tombstoned.cpp
Narayan Kamathbd863722017-06-01 18:50:12 +0100198static const std::string TOMBSTONE_DIR = "/data/tombstones/";
199static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
200static const std::string ANR_DIR = "/data/anr/";
201static const std::string ANR_FILE_PREFIX = "anr_";
Andy Hungd62f7e62024-01-11 15:47:52 -0800202static const std::string ANR_TRACE_FILE_PREFIX = "trace_";
Woody Lin20767a92022-11-29 15:50:24 +0800203static const std::string SHUTDOWN_CHECKPOINTS_DIR = "/data/system/shutdown-checkpoints/";
204static const std::string SHUTDOWN_CHECKPOINTS_FILE_PREFIX = "checkpoints-";
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700205
Felipe Lemee844a9d2016-09-21 15:01:39 -0700206// TODO: temporary variables and functions used during C++ refactoring
Nandana Dutt979388e2018-11-30 16:48:55 +0000207
Nandana Dutt5c390032019-03-12 10:52:56 +0000208#define RETURN_IF_USER_DENIED_CONSENT() \
209 if (ds.IsUserConsentDenied()) { \
210 MYLOGE("Returning early as user denied consent to share bugreport with calling app."); \
211 return Dumpstate::RunStatus::USER_CONSENT_DENIED; \
212 }
213
214// Runs func_ptr, but checks user consent before and after running it. Returns USER_CONSENT_DENIED
215// if consent is found to be denied.
216#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(func_ptr, ...) \
217 RETURN_IF_USER_DENIED_CONSENT(); \
218 func_ptr(__VA_ARGS__); \
219 RETURN_IF_USER_DENIED_CONSENT();
220
Rhed Jao5377d792020-07-16 17:37:39 +0800221// Runs func_ptr, and logs a duration report after it's finished.
222#define RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, ...) \
223 { \
224 DurationReporter duration_reporter_in_macro(log_title); \
225 func_ptr(__VA_ARGS__); \
226 }
227
228// Similar with RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK, an additional duration report
229// is output after a slow function is finished.
230#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(log_title, func_ptr, ...) \
231 RETURN_IF_USER_DENIED_CONSENT(); \
232 RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, __VA_ARGS__); \
233 RETURN_IF_USER_DENIED_CONSENT();
234
Chris Morinbc223142022-02-04 14:17:11 -0800235#define WAIT_TASK_WITH_CONSENT_CHECK(future) \
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800236 RETURN_IF_USER_DENIED_CONSENT(); \
Chris Morinbc223142022-02-04 14:17:11 -0800237 WaitForTask(future); \
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800238 RETURN_IF_USER_DENIED_CONSENT();
239
Sahana Raof35ed432019-07-12 10:47:52 +0100240static const char* WAKE_LOCK_NAME = "dumpstate_wakelock";
241
Rhed Jao5377d792020-07-16 17:37:39 +0800242// Names of parallel tasks, they are used for the DumpPool to identify the dump
243// task and the log title of the duration report.
244static const std::string DUMP_TRACES_TASK = "DUMP TRACES";
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800245static const std::string DUMP_INCIDENT_REPORT_TASK = "INCIDENT REPORT";
Aaron Huanga99452a2022-04-27 18:51:16 +0800246static const std::string DUMP_NETSTATS_PROTO_TASK = "DUMP NETSTATS PROTO";
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800247static const std::string DUMP_HALS_TASK = "DUMP HALS";
248static const std::string DUMP_BOARD_TASK = "dumpstate_board()";
Rhed Jaoe017f982020-07-21 17:58:41 +0800249static const std::string DUMP_CHECKINS_TASK = "DUMP CHECKINS";
Kean Mariotti306633e2022-09-05 16:30:47 +0000250static const std::string POST_PROCESS_UI_TRACES_TASK = "POST-PROCESS UI TRACES";
Rhed Jao5377d792020-07-16 17:37:39 +0800251
Nandana Dutt979388e2018-11-30 16:48:55 +0000252namespace android {
253namespace os {
254namespace {
255
256static int Open(std::string path, int flags, mode_t mode = 0) {
257 int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
258 if (fd == -1) {
259 MYLOGE("open(%s, %s)\n", path.c_str(), strerror(errno));
260 }
261 return fd;
262}
263
mhasank2d75c442020-06-11 15:05:25 -0700264static int OpenForWrite(std::string path) {
265 return Open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
266 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
267}
Nandana Dutt979388e2018-11-30 16:48:55 +0000268
269static int OpenForRead(std::string path) {
270 return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
271}
272
273bool CopyFile(int in_fd, int out_fd) {
274 char buf[4096];
275 ssize_t byte_count;
276 while ((byte_count = TEMP_FAILURE_RETRY(read(in_fd, buf, sizeof(buf)))) > 0) {
277 if (!android::base::WriteFully(out_fd, buf, byte_count)) {
278 return false;
279 }
280 }
281 return (byte_count != -1);
282}
283
284static bool CopyFileToFd(const std::string& input_file, int out_fd) {
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000285 MYLOGD("Going to copy file (%s) to %d\n", input_file.c_str(), out_fd);
Nandana Dutt979388e2018-11-30 16:48:55 +0000286
287 // Obtain a handle to the source file.
288 android::base::unique_fd in_fd(OpenForRead(input_file));
289 if (out_fd != -1 && in_fd.get() != -1) {
290 if (CopyFile(in_fd.get(), out_fd)) {
291 return true;
292 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000293 MYLOGE("Failed to copy file: %s\n", strerror(errno));
Nandana Dutt979388e2018-11-30 16:48:55 +0000294 }
295 return false;
296}
297
Nandana Duttd2f5f082019-01-18 17:13:52 +0000298static bool UnlinkAndLogOnError(const std::string& file) {
Nandana Dutt8ae16e62020-03-27 10:20:22 +0000299 if (file.empty()) {
300 return false;
301 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000302 if (unlink(file.c_str())) {
303 MYLOGE("Failed to unlink file (%s): %s\n", file.c_str(), strerror(errno));
Nandana Duttd2f5f082019-01-18 17:13:52 +0000304 return false;
305 }
306 return true;
307}
Nandana Dutt979388e2018-11-30 16:48:55 +0000308
Nikita Ioffea325a572019-05-16 19:49:47 +0100309int64_t GetModuleMetadataVersion() {
310 auto binder = defaultServiceManager()->getService(android::String16("package_native"));
311 if (binder == nullptr) {
312 MYLOGE("Failed to retrieve package_native service");
313 return 0L;
314 }
315 auto package_service = android::interface_cast<content::pm::IPackageManagerNative>(binder);
316 std::string package_name;
317 auto status = package_service->getModuleMetadataPackageName(&package_name);
318 if (!status.isOk()) {
319 MYLOGE("Failed to retrieve module metadata package name: %s", status.toString8().c_str());
320 return 0L;
321 }
Nandana Duttdb379fa2019-10-09 16:54:41 +0100322 MYLOGD("Module metadata package name: %s\n", package_name.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100323 int64_t version_code;
324 status = package_service->getVersionCodeForPackage(android::String16(package_name.c_str()),
325 &version_code);
326 if (!status.isOk()) {
327 MYLOGE("Failed to retrieve module metadata version: %s", status.toString8().c_str());
328 return 0L;
329 }
330 return version_code;
331}
332
mhasank2d75c442020-06-11 15:05:25 -0700333static bool PathExists(const std::string& path) {
334 struct stat sb;
335 return stat(path.c_str(), &sb) == 0;
336}
337
338static bool CopyFileToFile(const std::string& input_file, const std::string& output_file) {
339 if (input_file == output_file) {
340 MYLOGD("Skipping copying bugreport file since the destination is the same (%s)\n",
341 output_file.c_str());
342 return false;
343 }
344 else if (PathExists(output_file)) {
345 MYLOGD("Cannot overwrite an existing file (%s)\n", output_file.c_str());
346 return false;
347 }
348
349 MYLOGD("Going to copy bugreport file (%s) to %s\n", input_file.c_str(), output_file.c_str());
350 android::base::unique_fd out_fd(OpenForWrite(output_file));
351 return CopyFileToFd(input_file, out_fd.get());
352}
353
Nandana Dutt979388e2018-11-30 16:48:55 +0000354} // namespace
355} // namespace os
356} // namespace android
357
Felipe Leme678727a2016-09-21 17:22:11 -0700358static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
Felipe Lemebda15a02016-11-16 17:48:25 -0800359 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
Rhed Jaoe017f982020-07-21 17:58:41 +0800360 long dumpsysTimeoutMs = 0, int out_fd = STDOUT_FILENO) {
361 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs, out_fd);
362}
363static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
364 int out_fd) {
365 return ds.RunDumpsys(title, dumpsysArgs, Dumpstate::DEFAULT_DUMPSYS, 0, out_fd);
Felipe Leme678727a2016-09-21 17:22:11 -0700366}
367static int DumpFile(const std::string& title, const std::string& path) {
368 return ds.DumpFile(title, path);
369}
Felipe Lemee82a27d2016-01-05 13:35:44 -0800370
Felipe Lemee844a9d2016-09-21 15:01:39 -0700371// Relative directory (inside the zip) for all files copied as-is into the bugreport.
372static const std::string ZIP_ROOT_DIR = "FS";
373
Vishnu Naire97d6122018-01-18 13:58:56 -0800374static const std::string kProtoPath = "proto/";
375static const std::string kProtoExt = ".proto";
Jie Song9fbfad02017-06-20 16:29:42 -0700376static const std::string kDumpstateBoardFiles[] = {
377 "dumpstate_board.txt",
Felipe Leme95d6ca52017-08-01 16:35:56 -0700378 "dumpstate_board.bin"
Jie Song9fbfad02017-06-20 16:29:42 -0700379};
380static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
381
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700382static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Lemed071c682016-10-20 16:48:00 -0700383static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700384
Felipe Lemef0292972016-11-22 13:57:05 -0800385static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
386
Narayan Kamath8f788292017-05-25 13:20:39 +0100387/*
Narayan Kamathbd863722017-06-01 18:50:12 +0100388 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
Rhed Jao01dc0c62020-06-03 17:13:30 +0800389 * The returned vector is sorted by the mtimes of the dumps with descending
Chris Morinc2cba7a2022-02-01 17:06:50 -0800390 * order.
Narayan Kamath8f788292017-05-25 13:20:39 +0100391 */
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700392static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
Chris Morinc2cba7a2022-02-01 17:06:50 -0800393 const std::string& file_prefix) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100394 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100395
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700396 if (dump_dir == nullptr) {
397 MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno));
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700398 return std::vector<DumpData>();
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700399 }
400
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700401 std::vector<DumpData> dump_data;
Narayan Kamathbd863722017-06-01 18:50:12 +0100402 struct dirent* entry = nullptr;
403 while ((entry = readdir(dump_dir.get()))) {
404 if (entry->d_type != DT_REG) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100405 continue;
406 }
407
Narayan Kamathbd863722017-06-01 18:50:12 +0100408 const std::string base_name(entry->d_name);
409 if (base_name.find(file_prefix) != 0) {
410 continue;
411 }
412
413 const std::string abs_path = dir_path + base_name;
414 android::base::unique_fd fd(
415 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
416 if (fd == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700417 MYLOGW("Unable to open dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamathbd863722017-06-01 18:50:12 +0100418 break;
419 }
420
421 struct stat st = {};
422 if (fstat(fd, &st) == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700423 MYLOGW("Unable to stat dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamath8f788292017-05-25 13:20:39 +0100424 continue;
425 }
426
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700427 dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700428 }
Rhed Jao01dc0c62020-06-03 17:13:30 +0800429 if (!dump_data.empty()) {
430 std::sort(dump_data.begin(), dump_data.end(),
431 [](const auto& a, const auto& b) { return a.mtime > b.mtime; });
432 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100433
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700434 return dump_data;
Narayan Kamath8f788292017-05-25 13:20:39 +0100435}
436
Narayan Kamathbd863722017-06-01 18:50:12 +0100437static bool AddDumps(const std::vector<DumpData>::const_iterator start,
438 const std::vector<DumpData>::const_iterator end,
439 const char* type_name, const bool add_to_zip) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100440 bool dumped = false;
Narayan Kamathbd863722017-06-01 18:50:12 +0100441 for (auto it = start; it != end; ++it) {
442 const std::string& name = it->name;
443 const int fd = it->fd;
Narayan Kamath8f788292017-05-25 13:20:39 +0100444 dumped = true;
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100445
446 // Seek to the beginning of the file before dumping any data. A given
447 // DumpData entry might be dumped multiple times in the report.
448 //
449 // For example, the most recent ANR entry is dumped to the body of the
450 // main entry and it also shows up as a separate entry in the bugreport
451 // ZIP file.
452 if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) {
453 MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(),
454 strerror(errno));
455 }
456
Chris Morinc2cba7a2022-02-01 17:06:50 -0800457 if (add_to_zip) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800458 if (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd, /* timeout = */ 0ms) != OK) {
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100459 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100460 }
461 } else {
462 dump_file_from_fd(type_name, name.c_str(), fd);
463 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100464 }
465
466 return dumped;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700467}
468
Felipe Leme635ca312016-01-05 14:23:02 -0800469// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700470void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800471 char path[PATH_MAX];
472
473 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
474 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700475 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800476 char linkname[PATH_MAX];
477 ssize_t r = readlink(path, linkname, PATH_MAX);
478 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800479 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800480 return;
481 }
482 linkname[r] = '\0';
483
484 if (mount_points.find(linkname) == mount_points.end()) {
485 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700486 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700487 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
Felipe Leme635ca312016-01-05 14:23:02 -0800488 mount_points.insert(linkname);
489 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800490 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800491 }
492 }
493}
494
495void add_mountinfo() {
Felipe Leme678727a2016-09-21 17:22:11 -0700496 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800497 mount_points.clear();
Felipe Leme46b85da2016-11-21 17:40:45 -0800498 DurationReporter duration_reporter(title, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700499 for_each_pid(do_mountinfo, nullptr);
500 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800501}
502
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700503static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
504{
505 DIR *d;
506 struct dirent *de;
507 char path[PATH_MAX];
508
509 d = opendir(driverpath);
Yi Kong19d5c002018-07-20 13:39:55 -0700510 if (d == nullptr) {
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700511 return;
512 }
513
514 while ((de = readdir(d))) {
515 if (de->d_type != DT_LNK) {
516 continue;
517 }
518 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700519 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700520 }
521
522 closedir(d);
523}
524
Mark Salyzyn326842f2015-04-30 09:49:41 -0700525static bool skip_not_stat(const char *path) {
526 static const char stat[] = "/stat";
527 size_t len = strlen(path);
528 if (path[len - 1] == '/') { /* Directory? */
529 return false;
530 }
531 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
532}
533
Jeff Sharkey9df29d52023-02-06 14:26:30 -0700534static bool skip_wtf_strictmode(const char *path) {
535 if (strstr(path, "_wtf")) {
536 return true;
537 } else if (strstr(path, "_strictmode")) {
538 return true;
539 }
540 return false;
541}
542
Felipe Leme4c2d6632016-09-28 14:32:00 -0700543static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800544 return false;
545}
546
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700547unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700548
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800549//
550// stat offsets
551// Name units description
552// ---- ----- -----------
553// read I/Os requests number of read I/Os processed
554#define __STAT_READ_IOS 0
555// read merges requests number of read I/Os merged with in-queue I/O
556#define __STAT_READ_MERGES 1
557// read sectors sectors number of sectors read
558#define __STAT_READ_SECTORS 2
559// read ticks milliseconds total wait time for read requests
560#define __STAT_READ_TICKS 3
561// write I/Os requests number of write I/Os processed
562#define __STAT_WRITE_IOS 4
563// write merges requests number of write I/Os merged with in-queue I/O
564#define __STAT_WRITE_MERGES 5
565// write sectors sectors number of sectors written
566#define __STAT_WRITE_SECTORS 6
567// write ticks milliseconds total wait time for write requests
568#define __STAT_WRITE_TICKS 7
569// in_flight requests number of I/Os currently in flight
570#define __STAT_IN_FLIGHT 8
571// io_ticks milliseconds total time this block device has been active
572#define __STAT_IO_TICKS 9
573// time_in_queue milliseconds total wait time for all requests
574#define __STAT_IN_QUEUE 10
575#define __STAT_NUMBER_FIELD 11
576//
577// read I/Os, write I/Os
578// =====================
579//
580// These values increment when an I/O request completes.
581//
582// read merges, write merges
583// =========================
584//
585// These values increment when an I/O request is merged with an
586// already-queued I/O request.
587//
588// read sectors, write sectors
589// ===========================
590//
591// These values count the number of sectors read from or written to this
592// block device. The "sectors" in question are the standard UNIX 512-byte
593// sectors, not any device- or filesystem-specific block size. The
594// counters are incremented when the I/O completes.
595#define SECTOR_SIZE 512
596//
597// read ticks, write ticks
598// =======================
599//
600// These values count the number of milliseconds that I/O requests have
601// waited on this block device. If there are multiple I/O requests waiting,
602// these values will increase at a rate greater than 1000/second; for
603// example, if 60 read requests wait for an average of 30 ms, the read_ticks
604// field will increase by 60*30 = 1800.
605//
606// in_flight
607// =========
608//
609// This value counts the number of I/O requests that have been issued to
610// the device driver but have not yet completed. It does not include I/O
611// requests that are in the queue but not yet issued to the device driver.
612//
613// io_ticks
614// ========
615//
616// This value counts the number of milliseconds during which the device has
617// had I/O requests queued.
618//
619// time_in_queue
620// =============
621//
622// This value counts the number of milliseconds that I/O requests have waited
623// on this block device. If there are multiple I/O requests waiting, this
624// value will increase as the product of the number of milliseconds times the
625// number of requests waiting (see "read ticks" above for an example).
626#define S_TO_MS 1000
627//
628
Mark Salyzyn326842f2015-04-30 09:49:41 -0700629static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800630 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700631 bool z;
Yi Kong19d5c002018-07-20 13:39:55 -0700632 char *cp, *buffer = nullptr;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700633 size_t i = 0;
Josh Gao7c4258c2018-06-25 13:40:08 -0700634 FILE *fp = fdopen(dup(fd), "rb");
Mark Salyzyn326842f2015-04-30 09:49:41 -0700635 getline(&buffer, &i, fp);
636 fclose(fp);
637 if (!buffer) {
638 return -errno;
639 }
640 i = strlen(buffer);
641 while ((i > 0) && (buffer[i - 1] == '\n')) {
642 buffer[--i] = '\0';
643 }
644 if (!*buffer) {
645 free(buffer);
646 return 0;
647 }
648 z = true;
649 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800650 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700651 if (fields[i] != 0) {
652 z = false;
653 }
654 }
655 if (z) { /* never accessed */
656 free(buffer);
657 return 0;
658 }
659
Wei Wang509bb5d2017-06-09 14:42:12 -0700660 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
661 path += sizeof(BLK_DEV_SYS_DIR) - 1;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700662 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700663
664 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
665 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
666 "W-wait", "in-fli", "activ", "T-wait", path, buffer);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700667 free(buffer);
668
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800669 if (fields[__STAT_IO_TICKS]) {
670 unsigned long read_perf = 0;
671 unsigned long read_ios = 0;
672 if (fields[__STAT_READ_TICKS]) {
673 unsigned long long divisor = fields[__STAT_READ_TICKS]
674 * fields[__STAT_IO_TICKS];
675 read_perf = ((unsigned long long)SECTOR_SIZE
676 * fields[__STAT_READ_SECTORS]
677 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
678 / divisor;
679 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
680 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
681 / divisor;
682 }
683
684 unsigned long write_perf = 0;
685 unsigned long write_ios = 0;
686 if (fields[__STAT_WRITE_TICKS]) {
687 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
688 * fields[__STAT_IO_TICKS];
689 write_perf = ((unsigned long long)SECTOR_SIZE
690 * fields[__STAT_WRITE_SECTORS]
691 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
692 / divisor;
693 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
694 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
695 / divisor;
696 }
697
698 unsigned queue = (fields[__STAT_IN_QUEUE]
699 + (fields[__STAT_IO_TICKS] >> 1))
700 / fields[__STAT_IO_TICKS];
701
702 if (!write_perf && !write_ios) {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700703 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 -0800704 } else {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700705 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 -0800706 read_ios, write_perf, write_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800707 }
708
709 /* bugreport timeout factor adjustment */
710 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
711 worst_write_perf = write_perf;
712 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700713 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700714 return 0;
715}
716
Yao Chenbe3bbc12018-01-17 16:31:10 -0800717static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
718
Tom Cherryf4472f32020-08-05 09:31:17 -0700719// Returns the actual readable size of the given buffer or -1 on error.
720static long logcat_buffer_readable_size(const std::string& buffer) {
721 std::unique_ptr<logger_list, decltype(&android_logger_list_free)> logger_list{
722 android_logger_list_alloc(0, 0, 0), &android_logger_list_free};
723 auto logger = android_logger_open(logger_list.get(), android_name_to_log_id(buffer.c_str()));
724
725 return android_logger_get_log_readable_size(logger);
726}
727
728// Returns timeout in ms to read a list of buffers.
Yao Chenbe3bbc12018-01-17 16:31:10 -0800729static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
730 unsigned long timeout_ms = 0;
731 for (const auto& buffer : buffers) {
Tom Cherryf4472f32020-08-05 09:31:17 -0700732 long readable_size = logcat_buffer_readable_size(buffer);
733 if (readable_size > 0) {
734 // Engineering margin is ten-fold our guess.
735 timeout_ms += 10 * (readable_size + worst_write_perf) / worst_write_perf;
736 }
Yao Chenbe3bbc12018-01-17 16:31:10 -0800737 }
738 return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700739}
740
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800741// Opens a socket and returns its file descriptor.
742static int open_socket(const char* service);
743
Nandana Duttd2f5f082019-01-18 17:13:52 +0000744Dumpstate::ConsentCallback::ConsentCallback() : result_(UNAVAILABLE), start_time_(Nanotime()) {
745}
746
747android::binder::Status Dumpstate::ConsentCallback::onReportApproved() {
748 std::lock_guard<std::mutex> lock(lock_);
749 result_ = APPROVED;
750 MYLOGD("User approved consent to share bugreport\n");
Paul Chang0d2aad72020-02-13 20:04:03 +0800751
752 // Maybe copy screenshot so calling app can display the screenshot to the user as soon as
753 // consent is granted.
754 if (ds.options_->is_screenshot_copied) {
755 return android::binder::Status::ok();
756 }
757
758 if (!ds.options_->do_screenshot || ds.options_->screenshot_fd.get() == -1 ||
759 !ds.do_early_screenshot_) {
760 return android::binder::Status::ok();
761 }
762
763 bool copy_succeeded = android::os::CopyFileToFd(ds.screenshot_path_,
764 ds.options_->screenshot_fd.get());
765 ds.options_->is_screenshot_copied = copy_succeeded;
766 if (copy_succeeded) {
767 android::os::UnlinkAndLogOnError(ds.screenshot_path_);
768 }
Nandana Duttd2f5f082019-01-18 17:13:52 +0000769 return android::binder::Status::ok();
770}
771
772android::binder::Status Dumpstate::ConsentCallback::onReportDenied() {
773 std::lock_guard<std::mutex> lock(lock_);
774 result_ = DENIED;
775 MYLOGW("User denied consent to share bugreport\n");
776 return android::binder::Status::ok();
777}
778
779UserConsentResult Dumpstate::ConsentCallback::getResult() {
780 std::lock_guard<std::mutex> lock(lock_);
781 return result_;
782}
783
784uint64_t Dumpstate::ConsentCallback::getElapsedTimeMs() const {
Hunter Knepshieldf0a39052020-01-03 14:53:04 -0800785 return (Nanotime() - start_time_) / NANOS_PER_MILLI;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000786}
787
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700788void Dumpstate::PrintHeader() const {
Mårten Kongstad60195a72022-09-20 14:14:20 +0200789 std::string build, fingerprint, radio, bootloader, network, sdkversion;
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700790 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700791
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700792 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
793 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700794 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
795 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
796 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
Mårten Kongstad60195a72022-09-20 14:14:20 +0200797 sdkversion = android::base::GetProperty("ro.build.version.sdk", "(unknown)");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700798 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
Colin Crossf45fa6b2012-03-26 12:38:26 -0700799
Felipe Lemed8b94e52016-12-08 10:21:44 -0800800 printf("========================================================\n");
801 printf("== dumpstate: %s\n", date);
802 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700803
Felipe Lemed8b94e52016-12-08 10:21:44 -0800804 printf("\n");
805 printf("Build: %s\n", build.c_str());
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700806 // NOTE: fingerprint entry format is important for other tools.
Felipe Lemed8b94e52016-12-08 10:21:44 -0800807 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
808 printf("Bootloader: %s\n", bootloader.c_str());
809 printf("Radio: %s\n", radio.c_str());
810 printf("Network: %s\n", network.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100811 int64_t module_metadata_version = android::os::GetModuleMetadataVersion();
812 if (module_metadata_version != 0) {
813 printf("Module Metadata version: %" PRId64 "\n", module_metadata_version);
814 }
Mårten Kongstad60195a72022-09-20 14:14:20 +0200815 printf("Android SDK version: %s\n", sdkversion.c_str());
816 printf("SDK extensions: ");
817 RunCommandToFd(STDOUT_FILENO, "", {SDK_EXT_INFO, "--header"},
818 CommandOptions::WithTimeout(1).Always().DropRoot().Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700819
Felipe Lemed8b94e52016-12-08 10:21:44 -0800820 printf("Kernel: ");
Felipe Lemef0292972016-11-22 13:57:05 -0800821 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
Felipe Lemed8b94e52016-12-08 10:21:44 -0800822 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
Devin Moore09fde8d2023-03-21 16:28:22 +0000823 printf("Bootconfig: ");
824 DumpFileToFd(STDOUT_FILENO, "", "/proc/bootconfig");
Felipe Leme7709f8a2017-12-05 09:30:09 -0800825 printf("Uptime: ");
826 RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"},
827 CommandOptions::WithTimeout(1).Always().Build());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800828 printf("Bugreport format version: %s\n", version_.c_str());
Kevin Jeonfa64e642023-07-27 11:36:41 -0400829 printf(
830 "Dumpstate info: id=%d pid=%d dry_run=%d parallel_run=%d strict_run=%d args=%s "
831 "bugreport_mode=%s\n",
832 id_, pid_, PropertiesHelper::IsDryRun(), PropertiesHelper::IsParallelRun(),
833 PropertiesHelper::IsStrictRun(), options_->args.c_str(),
834 options_->bugreport_mode_string.c_str());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800835 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800836}
837
Felipe Leme24b66ee2016-06-16 10:55:26 -0700838// List of file extensions that can cause a zip file attachment to be rejected by some email
839// service providers.
840static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
841 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
842 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
843 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
844};
845
Vishnu Naire97d6122018-01-18 13:58:56 -0800846status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd,
847 std::chrono::milliseconds timeout = 0ms) {
Felipe Leme24b66ee2016-06-16 10:55:26 -0700848 std::string valid_name = entry_name;
849
850 // Rename extension if necessary.
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -0700851 size_t idx = entry_name.rfind('.');
Felipe Leme24b66ee2016-06-16 10:55:26 -0700852 if (idx != std::string::npos) {
853 std::string extension = entry_name.substr(idx);
854 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
855 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
856 valid_name = entry_name + ".renamed";
857 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
858 }
859 }
860
Felipe Leme6fe9db62016-02-12 09:04:16 -0800861 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
862 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Kevin Jeon9bbe0ac2022-05-05 22:05:43 +0000863 size_t flags = ZipWriter::kCompress | ZipWriter::kDefaultCompression;
864 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), flags,
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700865 get_mtime(fd, ds.now_));
Felipe Leme1d486fe2016-10-14 18:06:47 -0700866 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700867 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700868 ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800869 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800870 }
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000871 bool finished_entry = false;
872 auto finish_entry = [this, &finished_entry] {
873 if (!finished_entry) {
874 // This should only be called when we're going to return an earlier error,
875 // which would've been logged. This may imply the file is already corrupt
876 // and any further logging from FinishEntry is more likely to mislead than
877 // not.
878 this->zip_writer_->FinishEntry();
879 }
880 };
881 auto scope_guard = android::base::make_scope_guard(finish_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -0800882 auto start = std::chrono::steady_clock::now();
883 auto end = start + timeout;
884 struct pollfd pfd = {fd, POLLIN};
Felipe Lemee82a27d2016-01-05 13:35:44 -0800885
Felipe Leme770410d2016-01-26 17:07:14 -0800886 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800887 while (1) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800888 if (timeout.count() > 0) {
889 // lambda to recalculate the timeout.
890 auto time_left_ms = [end]() {
891 auto now = std::chrono::steady_clock::now();
892 auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
893 return std::max(diff.count(), 0LL);
894 };
895
896 int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
897 if (rc < 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000898 MYLOGE("Error in poll while adding from fd to zip entry %s:%s\n",
899 entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800900 return -errno;
901 } else if (rc == 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000902 MYLOGE("Timed out adding from fd to zip entry %s:%s Timeout:%lldms\n",
Vishnu Naire97d6122018-01-18 13:58:56 -0800903 entry_name.c_str(), strerror(errno), timeout.count());
904 return TIMED_OUT;
905 }
906 }
907
Zach Riggle22200402016-08-18 01:01:24 -0400908 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800909 if (bytes_read == 0) {
910 break;
911 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800912 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800913 return -errno;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800914 }
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700915 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800916 if (err) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700917 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800918 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800919 }
920 }
921
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700922 err = zip_writer_->FinishEntry();
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000923 finished_entry = true;
Felipe Leme1d486fe2016-10-14 18:06:47 -0700924 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700925 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800926 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800927 }
928
Vishnu Naire97d6122018-01-18 13:58:56 -0800929 return OK;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800930}
931
Felipe Leme1d486fe2016-10-14 18:06:47 -0700932bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
933 android::base::unique_fd fd(
934 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700935 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800936 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800937 return false;
938 }
939
Vishnu Naire97d6122018-01-18 13:58:56 -0800940 return (AddZipEntryFromFd(entry_name, fd.get()) == OK);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800941}
942
943/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700944static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800945 return (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) == OK) ? 0 : 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800946}
947
Felipe Leme1d486fe2016-10-14 18:06:47 -0700948void Dumpstate::AddDir(const std::string& dir, bool recursive) {
Felipe Leme678727a2016-09-21 17:22:11 -0700949 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
Felipe Leme46b85da2016-11-21 17:40:45 -0800950 DurationReporter duration_reporter(dir, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700951 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800952}
953
Felipe Leme1d486fe2016-10-14 18:06:47 -0700954bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800955 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Kevin Jeon9bbe0ac2022-05-05 22:05:43 +0000956 size_t flags = ZipWriter::kCompress | ZipWriter::kDefaultCompression;
957 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), flags, ds.now_);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700958 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700959 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700960 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800961 return false;
962 }
963
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700964 err = zip_writer_->WriteBytes(content.c_str(), content.length());
Felipe Leme1d486fe2016-10-14 18:06:47 -0700965 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700966 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700967 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800968 return false;
969 }
970
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700971 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700972 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700973 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800974 return false;
975 }
976
977 return true;
978}
979
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800980static void DoKmsg() {
981 struct stat st;
982 if (!stat(PSTORE_LAST_KMSG, &st)) {
983 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
984 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
985 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
986 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
987 } else {
988 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
989 DumpFile("LAST KMSG", "/proc/last_kmsg");
990 }
991}
992
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800993static void DoKernelLogcat() {
Yao Chenbe3bbc12018-01-17 16:31:10 -0800994 unsigned long timeout_ms = logcat_timeout({"kernel"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800995 RunCommand(
996 "KERNEL LOG",
997 {"logcat", "-b", "kernel", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
998 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
999}
1000
Nandana Duttdb379fa2019-10-09 16:54:41 +01001001static void DoSystemLogcat(time_t since) {
1002 char since_str[80];
1003 strftime(since_str, sizeof(since_str), "%Y-%m-%d %H:%M:%S.000", localtime(&since));
1004
1005 unsigned long timeout_ms = logcat_timeout({"main", "system", "crash"});
1006 RunCommand("SYSTEM LOG",
1007 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v", "-T",
1008 since_str},
1009 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1010}
1011
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001012static void DoRadioLogcat() {
1013 unsigned long timeout_ms = logcat_timeout({"radio"});
1014 RunCommand(
1015 "RADIO LOG",
1016 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1017 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
1018}
1019
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001020static void DoLogcat() {
Vishnu Nair6921f802017-11-22 09:17:23 -08001021 unsigned long timeout_ms;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001022 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
1023 // calculate timeout
Yao Chenbe3bbc12018-01-17 16:31:10 -08001024 timeout_ms = logcat_timeout({"main", "system", "crash"});
Tony Makae737652017-03-30 17:47:09 +01001025 RunCommand("SYSTEM LOG",
Vishnu Nair6921f802017-11-22 09:17:23 -08001026 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1027 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -08001028 timeout_ms = logcat_timeout({"events"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001029 RunCommand(
1030 "EVENT LOG",
1031 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001032 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Yao Chenbe3bbc12018-01-17 16:31:10 -08001033 timeout_ms = logcat_timeout({"stats"});
1034 RunCommand(
1035 "STATS LOG",
1036 {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001037 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001038 DoRadioLogcat();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001039
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001040 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001041 RunCommand("LAST LOGCAT", {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable",
1042 "-v", "uid", "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001043}
1044
Mike Ma5c267872019-08-21 11:31:34 -07001045static void DumpIncidentReport() {
Mike Ma5c267872019-08-21 11:31:34 -07001046 const std::string path = ds.bugreport_internal_dir_ + "/tmp_incident_report";
1047 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1048 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1049 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1050 if (fd < 0) {
1051 MYLOGE("Could not open %s to dump incident report.\n", path.c_str());
1052 return;
1053 }
Kevin Jeonfa64e642023-07-27 11:36:41 -04001054 RunCommandToFd(fd, "", {"incident", "-u"},
1055 CommandOptions::WithTimeout(PropertiesHelper::IsStrictRun() ? 20 : 120).Build());
Mike Ma5c267872019-08-21 11:31:34 -07001056 bool empty = 0 == lseek(fd, 0, SEEK_END);
1057 if (!empty) {
1058 // Use a different name from "incident.proto"
1059 // /proto/incident.proto is reserved for incident service dump
1060 // i.e. metadata for debugging.
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001061 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "incident_report" + kProtoExt,
1062 path);
1063 } else {
1064 unlink(path.c_str());
Mike Ma5c267872019-08-21 11:31:34 -07001065 }
Mike Ma5c267872019-08-21 11:31:34 -07001066}
1067
Aaron Huanga99452a2022-04-27 18:51:16 +08001068static void DumpNetstatsProto() {
1069 const std::string path = ds.bugreport_internal_dir_ + "/tmp_netstats_proto";
1070 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1071 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1072 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1073 if (fd < 0) {
1074 MYLOGE("Could not open %s to dump netstats proto.\n", path.c_str());
1075 return;
1076 }
1077 RunCommandToFd(fd, "", {"dumpsys", "netstats", "--proto"},
Kevin Jeon2fb3dd62022-09-28 18:48:55 +00001078 CommandOptions::WithTimeout(5).Build());
Aaron Huanga99452a2022-04-27 18:51:16 +08001079 bool empty = 0 == lseek(fd, 0, SEEK_END);
1080 if (!empty) {
1081 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "netstats" + kProtoExt,
1082 path);
1083 } else {
1084 unlink(path.c_str());
1085 }
1086}
1087
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001088static void MaybeAddSystemTraceToZip() {
1089 // This function copies into the .zip the system trace that was snapshotted
1090 // by the early call to MaybeSnapshotSystemTrace(), if any background
1091 // tracing was happening.
Kean Mariotti853b73a2023-07-27 12:40:30 +00001092 bool system_trace_exists = access(SYSTEM_TRACE_SNAPSHOT, F_OK) == 0;
1093 if (!system_trace_exists) {
1094 // No background trace was happening at the time MaybeSnapshotSystemTrace() was invoked.
1095 if (!PropertiesHelper::IsUserBuild()) {
1096 MYLOGI(
1097 "No system traces found. Check for previously uploaded traces by looking for "
1098 "go/trace-uuid in logcat")
1099 }
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001100 return;
1101 }
1102 ds.AddZipEntry(
1103 ZIP_ROOT_DIR + SYSTEM_TRACE_SNAPSHOT,
1104 SYSTEM_TRACE_SNAPSHOT);
1105 android::os::UnlinkAndLogOnError(SYSTEM_TRACE_SNAPSHOT);
1106}
1107
Sunny Goyal35949782019-11-19 15:54:36 -08001108static void DumpVisibleWindowViews() {
Sunny Goyal35949782019-11-19 15:54:36 -08001109 DurationReporter duration_reporter("VISIBLE WINDOW VIEWS");
1110 const std::string path = ds.bugreport_internal_dir_ + "/tmp_visible_window_views";
1111 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1112 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1113 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1114 if (fd < 0) {
1115 MYLOGE("Could not open %s to dump visible views.\n", path.c_str());
1116 return;
1117 }
1118 RunCommandToFd(fd, "", {"cmd", "window", "dump-visible-window-views"},
Kevin Jeon774abde2022-09-28 18:20:43 +00001119 CommandOptions::WithTimeout(10).Build());
Sunny Goyal35949782019-11-19 15:54:36 -08001120 bool empty = 0 == lseek(fd, 0, SEEK_END);
1121 if (!empty) {
1122 ds.AddZipEntry("visible_windows.zip", path);
1123 } else {
1124 MYLOGW("Failed to dump visible windows\n");
1125 }
1126 unlink(path.c_str());
1127}
1128
Jayachandran Ca94c7172017-06-10 15:08:12 -07001129static void DumpIpTablesAsRoot() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001130 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
1131 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +09001132 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001133 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +09001134 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
1135 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
1136 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
1137 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001138}
1139
Woody Lin20767a92022-11-29 15:50:24 +08001140static void DumpShutdownCheckpoints() {
1141 const bool shutdown_checkpoints_dumped = AddDumps(
1142 ds.shutdown_checkpoints_.begin(), ds.shutdown_checkpoints_.end(),
1143 "SHUTDOWN CHECKPOINTS", false /* add_to_zip */);
1144 if (!shutdown_checkpoints_dumped) {
1145 printf("*** NO SHUTDOWN CHECKPOINTS to dump in %s\n\n",
1146 SHUTDOWN_CHECKPOINTS_DIR.c_str());
1147 }
1148}
1149
David Andersond9ba4752018-12-11 18:26:59 -08001150static void DumpDynamicPartitionInfo() {
1151 if (!::android::base::GetBoolProperty("ro.boot.dynamic_partitions", false)) {
1152 return;
1153 }
1154
1155 RunCommand("LPDUMP", {"lpdump", "--all"});
David Anderson6650ade2019-10-02 15:18:59 -07001156 RunCommand("DEVICE-MAPPER", {"gsid", "dump-device-mapper"});
David Andersond9ba4752018-12-11 18:26:59 -08001157}
1158
Chris Morin5a50d482022-02-01 17:41:18 -08001159static void AddAnrTraceDir(const std::string& anr_traces_dir) {
Narayan Kamath8f788292017-05-25 13:20:39 +01001160 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
1161 anr_traces_dir.c_str());
1162
1163 // If we're here, dump_traces_path will always be a temporary file
1164 // (created with mkostemp or similar) that contains dumps taken earlier
1165 // on in the process.
1166 if (dump_traces_path != nullptr) {
Chris Morin5a50d482022-02-01 17:41:18 -08001167 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
1168 dump_traces_path);
1169 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
Narayan Kamath8f788292017-05-25 13:20:39 +01001170
1171 const int ret = unlink(dump_traces_path);
1172 if (ret == -1) {
1173 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
1174 strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -07001175 }
1176 }
1177
Narayan Kamathbd863722017-06-01 18:50:12 +01001178 // Add a specific message for the first ANR Dump.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001179 if (ds.anr_data_.size() > 0) {
Chris Morin5a50d482022-02-01 17:41:18 -08001180 // The "last" ANR will always be present in the body of the main entry.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001181 AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1,
Chris Morin5a50d482022-02-01 17:41:18 -08001182 "VM TRACES AT LAST ANR", false /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001183
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001184 // Historical ANRs are always included as separate entries in the bugreport zip file.
Chris Morin5a50d482022-02-01 17:41:18 -08001185 AddDumps(ds.anr_data_.begin(), ds.anr_data_.end(),
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001186 "HISTORICAL ANR", true /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001187 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +01001188 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
1189 }
Andy Hungd62f7e62024-01-11 15:47:52 -08001190
1191 // Add Java anr traces (such as generated by the Finalizer Watchdog).
1192 AddDumps(ds.anr_trace_data_.begin(), ds.anr_trace_data_.end(), "JAVA ANR TRACES",
1193 true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001194}
1195
1196static void AddAnrTraceFiles() {
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001197 std::string anr_traces_dir = "/data/anr";
Narayan Kamath8f788292017-05-25 13:20:39 +01001198
Chris Morin5a50d482022-02-01 17:41:18 -08001199 AddAnrTraceDir(anr_traces_dir);
Narayan Kamath8f788292017-05-25 13:20:39 +01001200
Makoto Onuki83ec63f2019-01-31 17:08:59 -08001201 RunCommand("ANR FILES", {"ls", "-lt", ANR_DIR});
1202
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001203 // Slow traces for slow operations.
Felipe Lemee184f662016-10-27 10:04:47 -07001204 struct stat st;
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001205 int i = 0;
1206 while (true) {
1207 const std::string slow_trace_path =
1208 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
1209 if (stat(slow_trace_path.c_str(), &st)) {
1210 // No traces file at this index, done with the files.
1211 break;
Felipe Lemee184f662016-10-27 10:04:47 -07001212 }
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001213 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
1214 i++;
Felipe Lemee184f662016-10-27 10:04:47 -07001215 }
1216}
1217
Wei Wang509bb5d2017-06-09 14:42:12 -07001218static void DumpBlockStatFiles() {
1219 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -07001220
Wei Wang1dc1ef52017-06-12 11:28:37 -07001221 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
1222
1223 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001224 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1225 return;
1226 }
1227
1228 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -07001229 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001230 if ((d->d_name[0] == '.')
1231 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1232 || (d->d_name[1] == '\0'))) {
1233 continue;
1234 }
1235 const std::string new_path =
1236 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1237 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1238 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1239 printf("\n");
1240 }
Wei Wang1dc1ef52017-06-12 11:28:37 -07001241 return;
Wei Wang509bb5d2017-06-09 14:42:12 -07001242}
Jayachandran Ca94c7172017-06-10 15:08:12 -07001243
1244static void DumpPacketStats() {
1245 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
Jayachandran Ca94c7172017-06-10 15:08:12 -07001246}
1247
1248static void DumpIpAddrAndRules() {
1249 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
Ray Chencbf278a2023-11-20 07:49:45 +00001250 RunCommand("NETWORK INTERFACES", {"ip", "-s", "link"});
Jayachandran Ca94c7172017-06-10 15:08:12 -07001251 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1252 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1253 RunCommand("IP RULES", {"ip", "rule", "show"});
1254 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1255}
1256
Nandana Dutt5c390032019-03-12 10:52:56 +00001257static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, int priority,
1258 std::chrono::milliseconds timeout,
1259 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001260 auto start = std::chrono::steady_clock::now();
Vishnu Naire97d6122018-01-18 13:58:56 -08001261 sp<android::IServiceManager> sm = defaultServiceManager();
1262 Dumpsys dumpsys(sm.get());
Vishnu Naire97d6122018-01-18 13:58:56 -08001263 Vector<String16> args;
1264 Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
Vishnu Naire97d6122018-01-18 13:58:56 -08001265 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1266 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001267 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001268 std::string path(title);
1269 path.append(" - ").append(String8(service).c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -08001270 size_t bytes_written = 0;
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001271 if (PropertiesHelper::IsDryRun()) {
1272 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1273 dumpsys.writeDumpFooter(STDOUT_FILENO, service, std::chrono::milliseconds(1));
1274 } else {
Devin Mooref492c1a2023-03-15 19:19:03 +00001275 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP | Dumpsys::TYPE_PID |
1276 Dumpsys::TYPE_CLIENTS | Dumpsys::TYPE_THREAD,
Devin Mooreae68df22023-02-24 20:59:51 +00001277 service, args);
1278 if (status == OK) {
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001279 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1280 std::chrono::duration<double> elapsed_seconds;
1281 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH &&
1282 service == String16("meminfo")) {
1283 // Use a longer timeout for meminfo, since 30s is not always enough.
1284 status = dumpsys.writeDump(STDOUT_FILENO, service, 60s,
1285 /* as_proto = */ false, elapsed_seconds,
1286 bytes_written);
1287 } else {
1288 status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
1289 /* as_proto = */ false, elapsed_seconds,
1290 bytes_written);
1291 }
1292 dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
1293 bool dump_complete = (status == OK);
1294 dumpsys.stopDumpThread(dump_complete);
Devin Moorecdfa4602023-03-16 20:49:39 +00001295 } else {
1296 MYLOGE("Failed to start dump thread for service: %s, status: %d",
1297 String8(service).c_str(), status);
Gavin Corkeryfac7e2b2021-07-08 22:39:02 +01001298 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001299 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001300
1301 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1302 std::chrono::steady_clock::now() - start);
1303 if (elapsed_duration > timeout) {
1304 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1305 elapsed_duration.count());
1306 break;
1307 }
1308 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001309 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001310}
1311
Vishnu Nair64afc022018-02-01 15:29:34 -08001312static void RunDumpsysText(const std::string& title, int priority,
1313 std::chrono::milliseconds timeout,
1314 std::chrono::milliseconds service_timeout) {
1315 DurationReporter duration_reporter(title);
1316 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1317 fsync(STDOUT_FILENO);
1318 RunDumpsysTextByPriority(title, priority, timeout, service_timeout);
1319}
1320
1321/* Dump all services registered with Normal or Default priority. */
Nandana Dutt5c390032019-03-12 10:52:56 +00001322static Dumpstate::RunStatus RunDumpsysTextNormalPriority(const std::string& title,
1323 std::chrono::milliseconds timeout,
1324 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001325 DurationReporter duration_reporter(title);
1326 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1327 fsync(STDOUT_FILENO);
1328 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout,
1329 service_timeout);
Nandana Dutt5c390032019-03-12 10:52:56 +00001330
1331 RETURN_IF_USER_DENIED_CONSENT();
1332
1333 return RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1334 service_timeout);
Vishnu Nair64afc022018-02-01 15:29:34 -08001335}
1336
Nandana Dutt5c390032019-03-12 10:52:56 +00001337static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priority,
1338 std::chrono::milliseconds timeout,
1339 std::chrono::milliseconds service_timeout) {
Vishnu Naire97d6122018-01-18 13:58:56 -08001340 sp<android::IServiceManager> sm = defaultServiceManager();
1341 Dumpsys dumpsys(sm.get());
1342 Vector<String16> args;
1343 Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
1344 DurationReporter duration_reporter(title);
1345
1346 auto start = std::chrono::steady_clock::now();
1347 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
1348 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001349 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001350 std::string path(kProtoPath);
1351 path.append(String8(service).c_str());
1352 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
1353 path.append("_CRITICAL");
1354 } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
1355 path.append("_HIGH");
1356 }
1357 path.append(kProtoExt);
Steven Morelandcbd69fc2021-07-20 20:45:43 +00001358 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP, service, args);
Vishnu Naire97d6122018-01-18 13:58:56 -08001359 if (status == OK) {
1360 status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
1361 bool dumpTerminated = (status == OK);
1362 dumpsys.stopDumpThread(dumpTerminated);
1363 }
1364 ZipWriter::FileEntry file_entry;
1365 ds.zip_writer_->GetLastEntry(&file_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -08001366
1367 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1368 std::chrono::steady_clock::now() - start);
1369 if (elapsed_duration > timeout) {
1370 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1371 elapsed_duration.count());
1372 break;
1373 }
1374 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001375 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001376}
1377
Nandana Dutta7db6342018-11-21 14:53:34 +00001378// Runs dumpsys on services that must dump first and will take less than 100ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001379static Dumpstate::RunStatus RunDumpsysCritical() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001380 RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1381 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Nandana Dutt5c390032019-03-12 10:52:56 +00001382
1383 RETURN_IF_USER_DENIED_CONSENT();
1384
1385 return RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1386 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Vishnu Nair780b1282017-10-10 13:57:24 -07001387}
1388
1389// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001390static Dumpstate::RunStatus RunDumpsysHigh() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001391 // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
1392 // high priority. Reduce timeout once they are able to dump in a shorter time or
1393 // moved to a parallel task.
1394 RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1395 /* timeout= */ 90s, /* service_timeout= */ 30s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001396
1397 RETURN_IF_USER_DENIED_CONSENT();
1398
1399 return RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1400 /* timeout= */ 5s, /* service_timeout= */ 1s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001401}
1402
1403// Runs dumpsys on services that must dump but can take up to 10s to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001404static Dumpstate::RunStatus RunDumpsysNormal() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001405 RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001406
1407 RETURN_IF_USER_DENIED_CONSENT();
1408
1409 return RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1410 /* timeout= */ 90s, /* service_timeout= */ 10s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001411}
1412
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001413/*
1414 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1415 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1416 * if it's not running in the parallel task.
1417 */
1418static void DumpHals(int out_fd = STDOUT_FILENO) {
Yifan Hong30528a22020-08-07 18:24:06 -07001419 RunCommand("HARDWARE HALS", {"lshal", "--all", "--types=all"},
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001420 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build(),
1421 false, out_fd);
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001422
Steven Moreland44cd9482018-01-04 16:24:13 -08001423 using android::hidl::manager::V1_0::IServiceManager;
1424 using android::hardware::defaultServiceManager;
1425
1426 sp<IServiceManager> sm = defaultServiceManager();
1427 if (sm == nullptr) {
1428 MYLOGE("Could not retrieve hwservicemanager to dump hals.\n");
1429 return;
1430 }
1431
1432 auto ret = sm->list([&](const auto& interfaces) {
1433 for (const std::string& interface : interfaces) {
1434 std::string cleanName = interface;
Steven Morelandc6b1fc22023-07-26 23:53:58 +00001435 std::replace_if(
1436 cleanName.begin(), cleanName.end(),
1437 [](char c) {
1438 return !isalnum(c) && std::string("@-_.").find(c) == std::string::npos;
1439 },
1440 '_');
Nandana Dutt979388e2018-11-30 16:48:55 +00001441 const std::string path = ds.bugreport_internal_dir_ + "/lshal_debug_" + cleanName;
Steven Moreland44cd9482018-01-04 16:24:13 -08001442
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001443 bool empty = false;
Steven Moreland44cd9482018-01-04 16:24:13 -08001444 {
1445 auto fd = android::base::unique_fd(
1446 TEMP_FAILURE_RETRY(open(path.c_str(),
1447 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1448 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1449 if (fd < 0) {
1450 MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str());
1451 continue;
1452 }
1453 RunCommandToFd(fd,
1454 "",
Steven Morelandc81cd3c2018-01-18 14:36:26 -08001455 {"lshal", "debug", "-E", interface},
Steven Moreland44cd9482018-01-04 16:24:13 -08001456 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1457
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001458 empty = 0 == lseek(fd, 0, SEEK_END);
Steven Moreland44cd9482018-01-04 16:24:13 -08001459 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001460 if (!empty) {
1461 ds.EnqueueAddZipEntryAndCleanupIfNeeded("lshal-debug/" + cleanName + ".txt",
1462 path);
1463 } else {
1464 unlink(path.c_str());
1465 }
Steven Moreland44cd9482018-01-04 16:24:13 -08001466 }
1467 });
1468
1469 if (!ret.isOk()) {
1470 MYLOGE("Could not list hals from hwservicemanager.\n");
1471 }
1472}
1473
Devin Moore8df81bb2022-06-08 22:47:02 +00001474// Dump all of the files that make up the vendor interface.
1475// See the files listed in dumpFileList() for the latest list of files.
1476static void DumpVintf() {
Devin Moore16271d92022-09-22 18:28:48 +00001477
1478 const std::string sku = android::base::GetProperty("ro.boot.product.hardware.sku", "");
1479 const auto vintfFiles = android::vintf::details::dumpFileList(sku);
Devin Moore8df81bb2022-06-08 22:47:02 +00001480 for (const auto vintfFile : vintfFiles) {
1481 struct stat st;
1482 if (stat(vintfFile.c_str(), &st) == 0) {
1483 if (S_ISDIR(st.st_mode)) {
1484 ds.AddDir(vintfFile, true /* recursive */);
1485 } else {
1486 ds.EnqueueAddZipEntryAndCleanupIfNeeded(ZIP_ROOT_DIR + vintfFile,
1487 vintfFile);
1488 }
1489 }
1490 }
1491}
1492
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001493static void DumpExternalFragmentationInfo() {
1494 struct stat st;
1495 if (stat("/proc/buddyinfo", &st) != 0) {
1496 MYLOGE("Unable to dump external fragmentation info\n");
1497 return;
1498 }
1499
1500 printf("------ EXTERNAL FRAGMENTATION INFO ------\n");
1501 std::ifstream ifs("/proc/buddyinfo");
1502 auto unusable_index_regex = std::regex{"Node\\s+([0-9]+),\\s+zone\\s+(\\S+)\\s+(.*)"};
1503 for (std::string line; std::getline(ifs, line);) {
1504 std::smatch match_results;
1505 if (std::regex_match(line, match_results, unusable_index_regex)) {
1506 std::stringstream free_pages(std::string{match_results[3]});
1507 std::vector<int> free_pages_per_order(std::istream_iterator<int>{free_pages},
1508 std::istream_iterator<int>());
1509
1510 int total_free_pages = 0;
1511 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1512 total_free_pages += (free_pages_per_order[i] * std::pow(2, i));
1513 }
1514
1515 printf("Node %s, zone %8s", match_results[1].str().c_str(),
1516 match_results[2].str().c_str());
1517
1518 int usable_free_pages = total_free_pages;
1519 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1520 auto unusable_index = (total_free_pages - usable_free_pages) /
1521 static_cast<double>(total_free_pages);
1522 printf(" %5.3f", unusable_index);
1523 usable_free_pages -= (free_pages_per_order[i] * std::pow(2, i));
1524 }
1525
1526 printf("\n");
1527 }
1528 }
1529 printf("\n");
1530}
1531
mhasankd451a472020-05-26 18:02:39 -07001532static void DumpstateLimitedOnly() {
EdenSue8fe4522023-11-20 15:37:23 +08001533 // Trimmed-down version of dumpstate to only include a allowlisted
mhasankd451a472020-05-26 18:02:39 -07001534 // set of logs (system log, event log, and system server / system app
1535 // crashes, and networking logs). See b/136273873 and b/138459828
1536 // for context.
1537 DurationReporter duration_reporter("DUMPSTATE");
1538 unsigned long timeout_ms;
1539 // calculate timeout
1540 timeout_ms = logcat_timeout({"main", "system", "crash"});
1541 RunCommand("SYSTEM LOG",
1542 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1543 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1544 timeout_ms = logcat_timeout({"events"});
1545 RunCommand(
1546 "EVENT LOG",
1547 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1548 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1549
1550 printf("========================================================\n");
1551 printf("== Networking Service\n");
1552 printf("========================================================\n");
1553
1554 RunDumpsys("DUMPSYS NETWORK_SERVICE_LIMITED", {"wifi", "-a"},
1555 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hugo Benichiaa162682020-10-30 23:28:56 +09001556 RunDumpsys("DUMPSYS CONNECTIVITY REQUESTS", {"connectivity", "requests"},
1557 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
mhasankd451a472020-05-26 18:02:39 -07001558
1559 printf("========================================================\n");
1560 printf("== Dropbox crashes\n");
1561 printf("========================================================\n");
1562
1563 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1564 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1565
1566 printf("========================================================\n");
1567 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1568 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1569 printf("========================================================\n");
1570 printf("== dumpstate: done (id %d)\n", ds.id_);
1571 printf("========================================================\n");
1572}
1573
Rhed Jaoe017f982020-07-21 17:58:41 +08001574/*
1575 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1576 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1577 * if it's not running in the parallel task.
1578 */
1579static void DumpCheckins(int out_fd = STDOUT_FILENO) {
1580 dprintf(out_fd, "========================================================\n");
1581 dprintf(out_fd, "== Checkins\n");
1582 dprintf(out_fd, "========================================================\n");
1583
1584 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"}, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001585 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"}, out_fd);
1586 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"}, out_fd);
1587 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"}, out_fd);
1588 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"}, out_fd);
1589}
1590
1591/*
1592 * Runs dumpsys on activity service to dump all application activities, services
1593 * and providers in the device.
1594 *
1595 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1596 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1597 * if it's not running in the parallel task.
1598 */
1599static void DumpAppInfos(int out_fd = STDOUT_FILENO) {
1600 dprintf(out_fd, "========================================================\n");
1601 dprintf(out_fd, "== Running Application Activities\n");
1602 dprintf(out_fd, "========================================================\n");
1603
1604 // The following dumpsys internally collects output from running apps, so it can take a long
1605 // time. So let's extend the timeout.
1606
1607 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1608
1609 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1610
1611 dprintf(out_fd, "========================================================\n");
1612 dprintf(out_fd, "== Running Application Services (platform)\n");
1613 dprintf(out_fd, "========================================================\n");
1614
1615 RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
1616 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1617
1618 dprintf(out_fd, "========================================================\n");
1619 dprintf(out_fd, "== Running Application Services (non-platform)\n");
1620 dprintf(out_fd, "========================================================\n");
1621
1622 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1623 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1624
1625 dprintf(out_fd, "========================================================\n");
1626 dprintf(out_fd, "== Running Application Providers (platform)\n");
1627 dprintf(out_fd, "========================================================\n");
1628
1629 RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
Rhed Jaob049f182021-01-11 21:08:43 +08001630 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001631
1632 dprintf(out_fd, "========================================================\n");
1633 dprintf(out_fd, "== Running Application Providers (non-platform)\n");
1634 dprintf(out_fd, "========================================================\n");
1635
1636 RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1637 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1638}
1639
Nandana Dutt5c390032019-03-12 10:52:56 +00001640// Dumps various things. Returns early with status USER_CONSENT_DENIED if user denies consent
1641// via the consent they are shown. Ignores other errors that occur while running various
1642// commands. The consent checking is currently done around long running tasks, which happen to
1643// be distributed fairly evenly throughout the function.
Kean Mariotti306633e2022-09-05 16:30:47 +00001644Dumpstate::RunStatus Dumpstate::dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001645 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001646
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001647 // Enqueue slow functions into the thread pool, if the parallel run is enabled.
Aaron Huanga99452a2022-04-27 18:51:16 +08001648 std::future<std::string> dump_hals, dump_incident_report, dump_board, dump_checkins,
Kean Mariotti306633e2022-09-05 16:30:47 +00001649 dump_netstats_report, post_process_ui_traces;
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001650 if (ds.dump_pool_) {
1651 // Pool was shutdown in DumpstateDefaultAfterCritical method in order to
Kean Mariotti306633e2022-09-05 16:30:47 +00001652 // drop root user. Restarts it.
1653 ds.dump_pool_->start(/* thread_counts = */3);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001654
Chris Morinbc223142022-02-04 14:17:11 -08001655 dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
1656 dump_incident_report = ds.dump_pool_->enqueueTask(
1657 DUMP_INCIDENT_REPORT_TASK, &DumpIncidentReport);
Aaron Huanga99452a2022-04-27 18:51:16 +08001658 dump_netstats_report = ds.dump_pool_->enqueueTask(
1659 DUMP_NETSTATS_PROTO_TASK, &DumpNetstatsProto);
Chris Morinbc223142022-02-04 14:17:11 -08001660 dump_board = ds.dump_pool_->enqueueTaskWithFd(
1661 DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
1662 dump_checkins = ds.dump_pool_->enqueueTaskWithFd(DUMP_CHECKINS_TASK, &DumpCheckins, _1);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001663 }
1664
Nandana Dutt5c390032019-03-12 10:52:56 +00001665 // Dump various things. Note that anything that takes "long" (i.e. several seconds) should
1666 // check intermittently (if it's intrerruptable like a foreach on pids) and/or should be wrapped
1667 // in a consent check (via RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK).
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001668 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001669 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001670 DumpBlockStatFiles();
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001671 DumpFile("MEMORY INFO", "/proc/meminfo");
1672 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001673 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001674
Kevin Jeon947922b2022-09-21 00:29:18 +00001675 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "BUGREPORT_PROCDUMP", {"bugreport_procdump"},
1676 CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001677
Sunny Goyal35949782019-11-19 15:54:36 -08001678 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpVisibleWindowViews);
1679
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001680 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1681 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1682 DumpFile("SLAB INFO", "/proc/slabinfo");
1683 DumpFile("ZONEINFO", "/proc/zoneinfo");
1684 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1685 DumpFile("BUDDYINFO", "/proc/buddyinfo");
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001686 DumpExternalFragmentationInfo();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001687
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001688 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001689
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001690 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001691 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001692
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001693 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001694 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_hals));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001695 } else {
1696 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_HALS_TASK, DumpHals);
1697 }
Steven Moreland81b429e2017-01-31 19:50:46 -08001698
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001699 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001700 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001701 struct stat s;
1702 if (stat("/proc/modules", &s) != 0) {
1703 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1704 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001705 RunCommand("LSMOD", {"lsmod"});
Woody Linc198f252021-05-04 16:37:11 +08001706 RunCommand("MODULES INFO",
1707 {"sh", "-c", "cat /proc/modules | cut -d' ' -f1 | "
1708 " while read MOD ; do echo modinfo:$MOD ; modinfo $MOD ; "
1709 "done"}, CommandOptions::AS_ROOT);
Felipe Lemee4eca582016-06-10 17:48:08 -07001710 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001711
Tom Cherryb87dbfa2020-07-28 11:28:53 -07001712 if (android::base::GetBoolProperty("ro.logd.kernel", false)) {
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001713 DoKernelLogcat();
1714 } else {
1715 do_dmesg();
1716 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001717
Devin Moore8df81bb2022-06-08 22:47:02 +00001718 DumpVintf();
1719
Felipe Lemef0292972016-11-22 13:57:05 -08001720 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001721
Jeff Brown1dc94e32014-09-11 14:15:27 -07001722 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001723 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001724
Jack Yu5a6b2e22020-08-14 18:13:35 +08001725 /* Dump Nfc NCI logs */
1726 ds.AddDir("/data/misc/nfc/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001727
Paul Chang0d2aad72020-02-13 20:04:03 +08001728 if (ds.options_->do_screenshot && !ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001729 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001730 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001731 }
1732
Felipe Lemee184f662016-10-27 10:04:47 -07001733 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001734
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001735 MaybeAddSystemTraceToZip();
1736
Narayan Kamath8f788292017-05-25 13:20:39 +01001737 // NOTE: tombstones are always added as separate entries in the zip archive
1738 // and are not interspersed with the main report.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001739 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
Narayan Kamathbd863722017-06-01 18:50:12 +01001740 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001741 if (!tombstones_dumped) {
1742 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001743 }
1744
Jayachandran Ca94c7172017-06-10 15:08:12 -07001745 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001746
Lorenzo Colitti807f2dd2022-05-27 12:48:37 +09001747 RunDumpsys("EBPF MAP STATS", {"connectivity", "trafficcontroller"});
Chenbo Feng276a3b62018-08-07 11:44:49 -07001748
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001749 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001750
Woody Lin20767a92022-11-29 15:50:24 +08001751 DumpShutdownCheckpoints();
1752
Jayachandran Ca94c7172017-06-10 15:08:12 -07001753 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001754
1755 dump_route_tables();
1756
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001757 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1758 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1759 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001760
Nandana Dutt5c390032019-03-12 10:52:56 +00001761 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysHigh);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001762
Chiachang Wang668ede42021-05-17 17:14:20 +08001763 // The dump mechanism in connectivity is refactored due to modularization work. Connectivity can
1764 // only register with a default priority(NORMAL priority). Dumpstate has to call connectivity
1765 // dump with priority parameters to dump high priority information.
1766 RunDumpsys("SERVICE HIGH connectivity", {"connectivity", "--dump-priority", "HIGH"},
1767 CommandOptions::WithTimeout(10).Build());
1768
Elliott Hughes23ccc622017-02-28 10:14:22 -08001769 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001770
Joe Onoratod38bc3a2023-06-29 15:48:28 -07001771 DumpFile("SYSTEM BUILD-TIME RELEASE FLAGS", "/system/etc/build_flags.json");
1772 DumpFile("SYSTEM_EXT BUILD-TIME RELEASE FLAGS", "/system_ext/etc/build_flags.json");
1773 DumpFile("PRODUCT BUILD-TIME RELEASE FLAGS", "/product/etc/build_flags.json");
1774 DumpFile("VENDOR BUILD-TIME RELEASE FLAGS", "/vendor/etc/build_flags.json");
1775
Mårten Kongstad5ad813f2023-09-28 10:09:18 +02001776 RunCommand("ACONFIG FLAGS", {PRINT_FLAGS},
1777 CommandOptions::WithTimeout(10).Always().DropRoot().Build());
Joe Onoratod38bc3a2023-06-29 15:48:28 -07001778
Jin Qianf334d662017-10-10 14:41:37 -07001779 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001780
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001781 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001782
Colin Crossf45fa6b2012-03-26 12:38:26 -07001783 /* Binder state is expensive to look at as it uses a lot of memory. */
Hridya Valsaraju920ba712020-02-09 16:27:01 -08001784 std::string binder_logs_dir = access("/dev/binderfs/binder_logs", R_OK) ?
1785 "/sys/kernel/debug/binder" : "/dev/binderfs/binder_logs";
1786
1787 DumpFile("BINDER FAILED TRANSACTION LOG", binder_logs_dir + "/failed_transaction_log");
1788 DumpFile("BINDER TRANSACTION LOG", binder_logs_dir + "/transaction_log");
1789 DumpFile("BINDER TRANSACTIONS", binder_logs_dir + "/transactions");
1790 DumpFile("BINDER STATS", binder_logs_dir + "/stats");
1791 DumpFile("BINDER STATE", binder_logs_dir + "/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001792
Yifan Hongd90cc652020-02-08 16:52:02 -08001793 ds.AddDir(SNAPSHOTCTL_LOG_DIR, false);
1794
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001795 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001796 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_board));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001797 } else {
1798 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
1799 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001800
Steven Moreland7440ddb2016-12-15 16:13:39 -08001801 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001802 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1803 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001804 // su does not exist on user builds, so try running without it.
1805 // This way any implementations of vril-dump that do not require
1806 // root can run on user builds.
1807 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001808 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001809 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001810 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001811 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001812 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001813 }
1814
Felipe Lemed8b94e52016-12-08 10:21:44 -08001815 printf("========================================================\n");
1816 printf("== Android Framework Services\n");
1817 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001818
Nandana Dutt5c390032019-03-12 10:52:56 +00001819 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001820
Jack He91ff2fe2021-02-18 18:23:43 -08001821 /* Dump Bluetooth HCI logs after getting bluetooth_manager dumpsys */
1822 ds.AddDir("/data/misc/bluetooth/logs", true);
1823
Rhed Jaoe017f982020-07-21 17:58:41 +08001824 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001825 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_checkins));
Rhed Jaoe017f982020-07-21 17:58:41 +08001826 } else {
1827 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_CHECKINS_TASK, DumpCheckins);
1828 }
Dianne Hackborn02bea972013-06-26 18:59:09 -07001829
Rhed Jaoc5f7ec32020-12-22 22:11:08 +08001830 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpAppInfos);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001831
Adrian Roos8b397ab2017-04-04 16:35:44 -07001832 printf("========================================================\n");
1833 printf("== Dropbox crashes\n");
1834 printf("========================================================\n");
1835
1836 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1837 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1838
Felipe Lemed8b94e52016-12-08 10:21:44 -08001839 printf("========================================================\n");
1840 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1841 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1842 printf("========================================================\n");
1843 printf("== dumpstate: done (id %d)\n", ds.id_);
1844 printf("========================================================\n");
Bookatz38472142018-09-28 10:20:24 -07001845
1846 printf("========================================================\n");
1847 printf("== Obtaining statsd metadata\n");
1848 printf("========================================================\n");
1849 // This differs from the usual dumpsys stats, which is the stats report data.
1850 RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
Mike Ma5c267872019-08-21 11:31:34 -07001851
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +09001852 // Add linker configuration directory
1853 ds.AddDir(LINKERCONFIG_DIR, true);
1854
Li Li830179f2022-01-04 12:53:29 -08001855 /* Dump frozen cgroupfs */
1856 dump_frozen_cgroupfs();
Li Li2eedd412021-06-30 15:11:53 -07001857
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001858 if (ds.dump_pool_) {
Aaron Huanga99452a2022-04-27 18:51:16 +08001859 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_netstats_report));
1860 } else {
1861 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_NETSTATS_PROTO_TASK,
1862 DumpNetstatsProto);
1863 }
1864
1865 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001866 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_incident_report));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001867 } else {
1868 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_INCIDENT_REPORT_TASK,
1869 DumpIncidentReport);
1870 }
Mike Ma5c267872019-08-21 11:31:34 -07001871
Kean Mariotti306633e2022-09-05 16:30:47 +00001872 MaybeAddUiTracesToZip();
1873
Nandana Dutt5c390032019-03-12 10:52:56 +00001874 return Dumpstate::RunStatus::OK;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001875}
1876
Nandana Dutt5c390032019-03-12 10:52:56 +00001877/*
1878 * Dumps state for the default case; drops root after it's no longer necessary.
1879 *
1880 * Returns RunStatus::OK if everything went fine.
1881 * Returns RunStatus::ERROR if there was an error.
1882 * Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport
1883 * with the caller.
1884 */
Jichao Lie89d9c12019-11-21 19:02:51 -08001885Dumpstate::RunStatus Dumpstate::DumpstateDefaultAfterCritical() {
Nandana Duttdb379fa2019-10-09 16:54:41 +01001886 // Capture first logcat early on; useful to take a snapshot before dumpstate logs take over the
1887 // buffer.
1888 DoLogcat();
1889 // Capture timestamp after first logcat to use in next logcat
1890 time_t logcat_ts = time(nullptr);
1891
Nandana Dutt4be45d12018-09-26 15:04:23 +01001892 /* collect stack traces from Dalvik and native processes (needs root) */
Chris Morinbc223142022-02-04 14:17:11 -08001893 std::future<std::string> dump_traces;
Rhed Jao5377d792020-07-16 17:37:39 +08001894 if (dump_pool_) {
1895 RETURN_IF_USER_DENIED_CONSENT();
1896 // One thread is enough since we only need to enqueue DumpTraces here.
1897 dump_pool_->start(/* thread_counts = */1);
1898
1899 // DumpTraces takes long time, post it to the another thread in the
1900 // pool, if pool is available
Chris Morinbc223142022-02-04 14:17:11 -08001901 dump_traces = dump_pool_->enqueueTask(
1902 DUMP_TRACES_TASK, &Dumpstate::DumpTraces, &ds, &dump_traces_path);
Rhed Jao5377d792020-07-16 17:37:39 +08001903 } else {
1904 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_TRACES_TASK, ds.DumpTraces,
1905 &dump_traces_path);
1906 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001907
1908 /* Run some operations that require root. */
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001909 if (!PropertiesHelper::IsDryRun()) {
Chris Morinc2cba7a2022-02-01 17:06:50 -08001910 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX);
1911 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX);
Andy Hungd62f7e62024-01-11 15:47:52 -08001912 ds.anr_trace_data_ = GetDumpFds(ANR_DIR, ANR_TRACE_FILE_PREFIX);
Woody Lin20767a92022-11-29 15:50:24 +08001913 ds.shutdown_checkpoints_ = GetDumpFds(
1914 SHUTDOWN_CHECKPOINTS_DIR, SHUTDOWN_CHECKPOINTS_FILE_PREFIX);
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001915 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001916
1917 ds.AddDir(RECOVERY_DIR, true);
1918 ds.AddDir(RECOVERY_DATA_DIR, true);
1919 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
Kelvin Zhang6eaa0f92022-09-12 09:29:19 -07001920 ds.AddDir(UPDATE_ENGINE_PREF_DIR, true);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001921 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1922 if (!PropertiesHelper::IsUserBuild()) {
1923 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1924 ds.AddDir(PROFILE_DATA_DIR_REF, true);
Calin Juravlef84d3692020-04-28 15:31:12 -07001925 ds.AddZipEntry(ZIP_ROOT_DIR + PACKAGE_DEX_USE_LIST, PACKAGE_DEX_USE_LIST);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001926 }
Jerry Changa1df8a92020-01-02 16:03:39 +08001927 ds.AddDir(PREREBOOT_DATA_DIR, false);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001928 add_mountinfo();
Peter Collingbourne78aa2942023-02-15 14:50:31 -08001929 for (const char* path : {"/proc/cpuinfo", "/proc/meminfo"}) {
1930 ds.AddZipEntry(ZIP_ROOT_DIR + path, path);
1931 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001932 DumpIpTablesAsRoot();
David Andersond9ba4752018-12-11 18:26:59 -08001933 DumpDynamicPartitionInfo();
Yifan Hong3945e1b2019-10-29 12:59:23 -07001934 ds.AddDir(OTA_METADATA_DIR, true);
Jeff Sharkey9df29d52023-02-06 14:26:30 -07001935 if (!PropertiesHelper::IsUserBuild()) {
1936 // Include dropbox entry files inside ZIP, but exclude
1937 // noisy WTF and StrictMode entries
1938 dump_files("", DROPBOX_DIR, skip_wtf_strictmode, _add_file_from_fd);
1939 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001940
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001941 // Capture any IPSec policies in play. No keys are exposed here.
Nandana Dutt4be45d12018-09-26 15:04:23 +01001942 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1943
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001944 // Dump IPsec stats. No keys are exposed here.
1945 DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
1946
Nandana Dutt4be45d12018-09-26 15:04:23 +01001947 // Run ss as root so we can see socket marks.
1948 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1949
1950 // Run iotop as root to show top 100 IO threads
1951 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1952
Erick Reyese68df822019-02-11 14:46:36 -08001953 // Gather shared memory buffer info if the product implements it
Hridya Valsaraju1da80c52021-01-09 22:10:11 -08001954 RunCommand("Dmabuf dump", {"dmabuf_dump"});
1955 RunCommand("Dmabuf per-buffer/per-exporter/per-device stats", {"dmabuf_dump", "-b"});
Erick Reyese68df822019-02-11 14:46:36 -08001956
Minchan Kim22c6a1e2019-09-30 15:58:10 -07001957 DumpFile("PSI cpu", "/proc/pressure/cpu");
1958 DumpFile("PSI memory", "/proc/pressure/memory");
1959 DumpFile("PSI io", "/proc/pressure/io");
1960
Steven Moreland9379c462023-12-21 02:04:27 +00001961 ds.AddZipEntry(ZIP_ROOT_DIR + KERNEL_CONFIG, KERNEL_CONFIG);
1962
Mårten Kongstad60195a72022-09-20 14:14:20 +02001963 RunCommand("SDK EXTENSIONS", {SDK_EXT_INFO, "--dump"},
1964 CommandOptions::WithTimeout(10).Always().DropRoot().Build());
1965
Rhed Jao5377d792020-07-16 17:37:39 +08001966 if (dump_pool_) {
1967 RETURN_IF_USER_DENIED_CONSENT();
Chris Morinbc223142022-02-04 14:17:11 -08001968 WaitForTask(std::move(dump_traces));
Rhed Jao5377d792020-07-16 17:37:39 +08001969
Chris Morinbc223142022-02-04 14:17:11 -08001970 // Current running thread in the pool is the root user also. Delete
1971 // the pool and make a new one later to ensure none of threads in the pool are root.
1972 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao5377d792020-07-16 17:37:39 +08001973 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001974 if (!DropRootUser()) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001975 return Dumpstate::RunStatus::ERROR;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001976 }
1977
Nandana Dutt5c390032019-03-12 10:52:56 +00001978 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttdb379fa2019-10-09 16:54:41 +01001979 Dumpstate::RunStatus status = dumpstate();
1980 // Capture logcat since the last time we did it.
1981 DoSystemLogcat(logcat_ts);
1982 return status;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001983}
1984
Rhed Jaob5685b32020-08-14 17:19:17 +08001985// Common states for telephony and wifi which are needed to be collected before
1986// dumpstate drop the root user.
1987static void DumpstateRadioAsRoot() {
1988 DumpIpTablesAsRoot();
1989 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1990}
1991
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001992// This method collects common dumpsys for telephony and wifi. Typically, wifi
1993// reports are fine to include all information, but telephony reports on user
1994// builds need to strip some content (see DumpstateTelephonyOnly).
1995static void DumpstateRadioCommon(bool include_sensitive_info = true) {
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001996 // We need to be picky about some stuff for telephony reports on user builds.
1997 if (!include_sensitive_info) {
1998 // Only dump the radio log buffer (other buffers and dumps contain too much unrelated info).
1999 DoRadioLogcat();
2000 } else {
Rhed Jaob5685b32020-08-14 17:19:17 +08002001 // DumpHals takes long time, post it to the another thread in the pool,
2002 // if pool is available.
Chris Morinbc223142022-02-04 14:17:11 -08002003 std::future<std::string> dump_hals;
Rhed Jaob5685b32020-08-14 17:19:17 +08002004 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002005 dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
Rhed Jaob5685b32020-08-14 17:19:17 +08002006 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002007 // Contains various system properties and process startup info.
2008 do_dmesg();
2009 // Logs other than the radio buffer may contain package/component names and potential PII.
2010 DoLogcat();
2011 // Too broad for connectivity problems.
2012 DoKmsg();
Rhed Jaob5685b32020-08-14 17:19:17 +08002013 // DumpHals contains unrelated hardware info (camera, NFC, biometrics, ...).
2014 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002015 WaitForTask(std::move(dump_hals));
Rhed Jaob5685b32020-08-14 17:19:17 +08002016 } else {
2017 RUN_SLOW_FUNCTION_AND_LOG(DUMP_HALS_TASK, DumpHals);
2018 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002019 }
2020
Jayachandran Ca94c7172017-06-10 15:08:12 -07002021 DumpPacketStats();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002022 DumpIpAddrAndRules();
2023 dump_route_tables();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002024 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
2025 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08002026}
2027
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002028// We use "telephony" here for legacy reasons, though this now really means "connectivity" (cellular
2029// + wifi + networking). This method collects dumpsys for connectivity debugging only. General rules
2030// for what can be included on user builds: all reported information MUST directly relate to
2031// connectivity debugging or customer support and MUST NOT contain unrelated personally identifiable
2032// information. This information MUST NOT identify user-installed packages (UIDs are OK, package
2033// names are not), and MUST NOT contain logs of user application traffic.
2034// TODO(b/148168577) rename this and other related fields/methods to "connectivity" instead.
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08002035static void DumpstateTelephonyOnly(const std::string& calling_package) {
mukesh agrawal253dad42018-01-23 21:59:59 -08002036 DurationReporter duration_reporter("DUMPSTATE");
Jichao Lie89d9c12019-11-21 19:02:51 -08002037
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002038 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
mukesh agrawal253dad42018-01-23 21:59:59 -08002039
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002040 const bool include_sensitive_info = !PropertiesHelper::IsUserBuild();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002041
Rhed Jaob5685b32020-08-14 17:19:17 +08002042 DumpstateRadioAsRoot();
2043 if (!DropRootUser()) {
2044 return;
2045 }
2046
2047 // Starts thread pool after the root user is dropped, and two additional threads
2048 // are created for DumpHals in the DumpstateRadioCommon and DumpstateBoard.
Chris Morinbc223142022-02-04 14:17:11 -08002049 std::future<std::string> dump_board;
Rhed Jaob5685b32020-08-14 17:19:17 +08002050 if (ds.dump_pool_) {
2051 ds.dump_pool_->start(/*thread_counts =*/2);
2052
2053 // DumpstateBoard takes long time, post it to the another thread in the pool,
2054 // if pool is available.
Chris Morinbc223142022-02-04 14:17:11 -08002055 dump_board = ds.dump_pool_->enqueueTaskWithFd(
2056 DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
Rhed Jaob5685b32020-08-14 17:19:17 +08002057 }
2058
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002059 DumpstateRadioCommon(include_sensitive_info);
2060
2061 if (include_sensitive_info) {
2062 // Contains too much unrelated PII, and given the unstructured nature of sysprops, we can't
2063 // really cherrypick all of the connectivity-related ones. Apps generally have no business
2064 // reading these anyway, and there should be APIs to supply the info in a more app-friendly
2065 // way.
2066 RunCommand("SYSTEM PROPERTIES", {"getprop"});
2067 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002068
2069 printf("========================================================\n");
2070 printf("== Android Framework Services\n");
2071 printf("========================================================\n");
2072
Vishnu Nair652cc802017-11-30 15:18:30 -08002073 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2074 SEC_TO_MSEC(10));
Hunter Knepshield31cbae12021-05-11 16:23:24 -07002075 RunDumpsys("DUMPSYS", {"vcn_management"}, CommandOptions::WithTimeout(90).Build(),
2076 SEC_TO_MSEC(10));
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08002077 if (include_sensitive_info) {
2078 // Carrier apps' services will be dumped below in dumpsys activity service all-non-platform.
2079 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
2080 SEC_TO_MSEC(10));
2081 } else {
2082 // If the caller is a carrier app and has a carrier service, dump it here since we aren't
2083 // running dumpsys activity service all-non-platform below. Due to the increased output, we
2084 // give a higher timeout as well.
2085 RunDumpsys("DUMPSYS", {"carrier_config", "--requesting-package", calling_package},
2086 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(30));
2087 }
2088 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002089 RunDumpsys("DUMPSYS", {"netpolicy"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2090 RunDumpsys("DUMPSYS", {"network_management"}, CommandOptions::WithTimeout(90).Build(),
Sooraj Sasindrane8d98912018-04-20 11:31:55 -07002091 SEC_TO_MSEC(10));
Hunter Knepshield0fe51b12020-03-05 16:58:20 -08002092 RunDumpsys("DUMPSYS", {"telephony.registry"}, CommandOptions::WithTimeout(90).Build(),
2093 SEC_TO_MSEC(10));
Jack Yu773cc032023-03-16 22:43:39 -07002094 RunDumpsys("DUMPSYS", {"isub"}, CommandOptions::WithTimeout(90).Build(),
2095 SEC_TO_MSEC(10));
Grant Menke9bf3b2b2023-02-24 13:11:07 -08002096 RunDumpsys("DUMPSYS", {"telecom"}, CommandOptions::WithTimeout(90).Build(),
2097 SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002098 if (include_sensitive_info) {
2099 // Contains raw IP addresses, omit from reports on user builds.
2100 RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2101 // Contains raw destination IP/MAC addresses, omit from reports on user builds.
2102 RunDumpsys("DUMPSYS", {"connmetrics"}, CommandOptions::WithTimeout(90).Build(),
2103 SEC_TO_MSEC(10));
2104 // Contains package/component names, omit from reports on user builds.
2105 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
2106 SEC_TO_MSEC(10));
2107 // Contains package names, but should be relatively simple to remove them (also contains
2108 // UIDs already), omit from reports on user builds.
2109 RunDumpsys("BATTERYSTATS", {"deviceidle"}, CommandOptions::WithTimeout(90).Build(),
2110 SEC_TO_MSEC(10));
2111 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002112
2113 printf("========================================================\n");
2114 printf("== Running Application Services\n");
2115 printf("========================================================\n");
2116
2117 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
2118
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002119 if (include_sensitive_info) {
2120 printf("========================================================\n");
2121 printf("== Running Application Services (non-platform)\n");
2122 printf("========================================================\n");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002123
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002124 // Contains package/component names and potential PII, omit from reports on user builds.
2125 // To get dumps of the active CarrierService(s) on user builds, we supply an argument to the
2126 // carrier_config dumpsys instead.
2127 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
2128 DUMPSYS_COMPONENTS_OPTIONS);
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002129
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002130 printf("========================================================\n");
2131 printf("== Checkins\n");
2132 printf("========================================================\n");
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002133
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002134 // Contains package/component names, omit from reports on user builds.
2135 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
2136 }
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002137
2138 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07002139 printf("== dumpstate: done (id %d)\n", ds.id_);
2140 printf("========================================================\n");
Rhed Jaob5685b32020-08-14 17:19:17 +08002141
2142 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002143 WaitForTask(std::move(dump_board));
Rhed Jaob5685b32020-08-14 17:19:17 +08002144 } else {
2145 RUN_SLOW_FUNCTION_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
2146 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002147}
2148
mukesh agrawal253dad42018-01-23 21:59:59 -08002149// This method collects dumpsys for wifi debugging only
2150static void DumpstateWifiOnly() {
2151 DurationReporter duration_reporter("DUMPSTATE");
2152
Rhed Jaob5685b32020-08-14 17:19:17 +08002153 DumpstateRadioAsRoot();
2154 if (!DropRootUser()) {
2155 return;
2156 }
2157
2158 // Starts thread pool after the root user is dropped. Only one additional
2159 // thread is needed for DumpHals in the DumpstateRadioCommon.
2160 if (ds.dump_pool_) {
2161 ds.dump_pool_->start(/*thread_counts =*/1);
2162 }
2163
mukesh agrawal253dad42018-01-23 21:59:59 -08002164 DumpstateRadioCommon();
2165
2166 printf("========================================================\n");
2167 printf("== Android Framework Services\n");
2168 printf("========================================================\n");
2169
2170 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2171 SEC_TO_MSEC(10));
2172 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
2173 SEC_TO_MSEC(10));
2174
2175 printf("========================================================\n");
2176 printf("== dumpstate: done (id %d)\n", ds.id_);
2177 printf("========================================================\n");
2178}
2179
Elis Elliott8e401ad2023-08-08 11:18:59 +00002180// Collects a lightweight dumpstate to be used for debugging onboarding related flows.
2181static void DumpstateOnboardingOnly() {
2182 ds.AddDir(LOGPERSIST_DATA_DIR, false);
2183}
2184
Nandana Duttcf419a72019-03-14 10:40:17 +00002185Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
Gavin Corkery789d7a52021-02-24 23:52:35 +00002186 const std::string temp_file_pattern = ds.bugreport_internal_dir_ + "/dumptrace_XXXXXX";
Nandana Duttfaafd522019-03-11 09:23:09 +00002187 const size_t buf_size = temp_file_pattern.length() + 1;
2188 std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
2189 memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
2190
2191 // Create a new, empty file to receive all trace dumps.
2192 //
2193 // TODO: This can be simplified once we remove support for the old style
2194 // dumps. We can have a file descriptor passed in to dump_traces instead
2195 // of creating a file, closing it and then reopening it again.
2196 android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
2197 if (fd < 0) {
2198 MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002199 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002200 }
2201
2202 // Nobody should have access to this temporary file except dumpstate, but we
2203 // temporarily grant 'read' to 'others' here because this file is created
2204 // when tombstoned is still running as root, but dumped after dropping. This
2205 // can go away once support for old style dumping has.
2206 const int chmod_ret = fchmod(fd, 0666);
2207 if (chmod_ret < 0) {
2208 MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002209 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002210 }
2211
2212 std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
2213 if (proc.get() == nullptr) {
2214 MYLOGE("opendir /proc failed: %s\n", strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002215 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002216 }
2217
2218 // Number of times process dumping has timed out. If we encounter too many
2219 // failures, we'll give up.
2220 int timeout_failures = 0;
2221 bool dalvik_found = false;
2222
Jayant Chowdharya0a8eb22022-05-20 03:30:09 +00002223 const std::set<int> hal_pids = get_interesting_pids();
Nandana Duttfaafd522019-03-11 09:23:09 +00002224
2225 struct dirent* d;
2226 while ((d = readdir(proc.get()))) {
Nandana Duttcf419a72019-03-14 10:40:17 +00002227 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttfaafd522019-03-11 09:23:09 +00002228 int pid = atoi(d->d_name);
2229 if (pid <= 0) {
2230 continue;
2231 }
2232
Kevin Jeond0f8a982023-04-07 14:27:11 -04002233 // Skip cached processes.
2234 if (IsCached(pid)) {
2235 // For consistency, the header and footer to this message match those
2236 // dumped by debuggerd in the success case.
2237 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
2238 dprintf(fd, "Dump skipped for cached process.\n");
2239 dprintf(fd, "---- end %d ----", pid);
2240 continue;
2241 }
2242
Nandana Duttfaafd522019-03-11 09:23:09 +00002243 const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
2244 std::string exe;
2245 if (!android::base::Readlink(link_name, &exe)) {
2246 continue;
2247 }
2248
2249 bool is_java_process;
2250 if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
2251 // Don't bother dumping backtraces for the zygote.
2252 if (IsZygote(pid)) {
2253 continue;
2254 }
2255
2256 dalvik_found = true;
2257 is_java_process = true;
2258 } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
2259 is_java_process = false;
2260 } else {
2261 // Probably a native process we don't care about, continue.
2262 continue;
2263 }
2264
2265 // If 3 backtrace dumps fail in a row, consider debuggerd dead.
2266 if (timeout_failures == 3) {
2267 dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
2268 break;
2269 }
2270
2271 const uint64_t start = Nanotime();
2272 const int ret = dump_backtrace_to_file_timeout(
Kevin Jeonb8a39362023-04-04 15:00:34 -04002273 pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace, 3, fd);
Nandana Duttfaafd522019-03-11 09:23:09 +00002274
2275 if (ret == -1) {
2276 // For consistency, the header and footer to this message match those
2277 // dumped by debuggerd in the success case.
2278 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
2279 dprintf(fd, "Dump failed, likely due to a timeout.\n");
2280 dprintf(fd, "---- end %d ----", pid);
2281 timeout_failures++;
2282 continue;
2283 }
2284
2285 // We've successfully dumped stack traces, reset the failure count
2286 // and write a summary of the elapsed time to the file and continue with the
2287 // next process.
2288 timeout_failures = 0;
2289
2290 dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
2291 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
2292 }
2293
2294 if (!dalvik_found) {
2295 MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
2296 }
2297
Nandana Duttcf419a72019-03-14 10:40:17 +00002298 *path = file_name_buf.release();
2299 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002300}
2301
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002302static dumpstate_hal_hidl::DumpstateMode GetDumpstateHalModeHidl(
2303 const Dumpstate::BugreportMode bugreport_mode) {
2304 switch (bugreport_mode) {
2305 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2306 return dumpstate_hal_hidl::DumpstateMode::FULL;
2307 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2308 return dumpstate_hal_hidl::DumpstateMode::INTERACTIVE;
2309 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2310 return dumpstate_hal_hidl::DumpstateMode::REMOTE;
2311 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2312 return dumpstate_hal_hidl::DumpstateMode::WEAR;
2313 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2314 return dumpstate_hal_hidl::DumpstateMode::CONNECTIVITY;
2315 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2316 return dumpstate_hal_hidl::DumpstateMode::WIFI;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002317 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002318 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2319 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2320 }
2321 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2322}
2323
2324static dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode GetDumpstateHalModeAidl(
2325 const Dumpstate::BugreportMode bugreport_mode) {
2326 switch (bugreport_mode) {
2327 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2328 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::FULL;
2329 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2330 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::INTERACTIVE;
2331 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2332 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::REMOTE;
2333 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2334 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WEAR;
2335 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2336 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::CONNECTIVITY;
2337 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2338 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WIFI;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002339 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002340 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2341 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2342 }
2343 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2344}
2345
2346static void DoDumpstateBoardHidl(
2347 const sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_1_0,
2348 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2349 const Dumpstate::BugreportMode bugreport_mode,
2350 const size_t timeout_sec) {
2351
2352 using ScopedNativeHandle =
2353 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
2354 ScopedNativeHandle handle(native_handle_create(static_cast<int>(dumpstate_fds.size()), 0),
2355 [](native_handle_t* handle) {
2356 // we don't close file handle's here
2357 // via native_handle_close(handle)
2358 // instead we let dumpstate_fds close the file handles when
2359 // dumpstate_fds gets destroyed
2360 native_handle_delete(handle);
2361 });
2362 if (handle == nullptr) {
2363 MYLOGE("Could not create native_handle for dumpstate HAL\n");
2364 return;
2365 }
2366
2367 for (size_t i = 0; i < dumpstate_fds.size(); i++) {
2368 handle.get()->data[i] = dumpstate_fds[i].get();
2369 }
2370
2371 // Prefer version 1.1 if available. New devices launching with R are no longer allowed to
2372 // implement just 1.0.
2373 const char* descriptor_to_kill;
2374 using DumpstateBoardTask = std::packaged_task<bool()>;
2375 DumpstateBoardTask dumpstate_board_task;
2376 sp<dumpstate_hal_hidl::IDumpstateDevice> dumpstate_hal(
2377 dumpstate_hal_hidl::IDumpstateDevice::castFrom(dumpstate_hal_1_0));
2378 if (dumpstate_hal != nullptr) {
2379 MYLOGI("Using IDumpstateDevice v1.1 HIDL HAL");
2380
2381 dumpstate_hal_hidl::DumpstateMode dumpstate_hal_mode =
2382 GetDumpstateHalModeHidl(bugreport_mode);
2383
2384 descriptor_to_kill = dumpstate_hal_hidl::IDumpstateDevice::descriptor;
2385 dumpstate_board_task =
2386 DumpstateBoardTask([timeout_sec, dumpstate_hal_mode, dumpstate_hal, &handle]() -> bool {
2387 ::android::hardware::Return<dumpstate_hal_hidl::DumpstateStatus> status =
2388 dumpstate_hal->dumpstateBoard_1_1(handle.get(), dumpstate_hal_mode,
2389 SEC_TO_MSEC(timeout_sec));
2390 if (!status.isOk()) {
2391 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2392 return false;
2393 } else if (status != dumpstate_hal_hidl::DumpstateStatus::OK) {
2394 MYLOGE("dumpstateBoard failed with DumpstateStatus::%s\n",
2395 dumpstate_hal_hidl::toString(status).c_str());
2396 return false;
2397 }
2398 return true;
2399 });
2400 } else {
2401 MYLOGI("Using IDumpstateDevice v1.0 HIDL HAL");
2402
2403 descriptor_to_kill = dumpstate_hal_hidl_1_0::IDumpstateDevice::descriptor;
2404 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal_1_0, &handle]() -> bool {
2405 ::android::hardware::Return<void> status =
2406 dumpstate_hal_1_0->dumpstateBoard(handle.get());
2407 if (!status.isOk()) {
2408 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2409 return false;
2410 }
2411 return true;
2412 });
2413 }
2414 auto result = dumpstate_board_task.get_future();
2415 std::thread(std::move(dumpstate_board_task)).detach();
2416
2417 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2418 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2419 if (!android::base::SetProperty(
2420 "ctl.interface_restart",
2421 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2422 MYLOGE("Couldn't restart dumpstate HAL\n");
2423 }
2424 }
2425 // Wait some time for init to kill dumpstate vendor HAL
2426 constexpr size_t killing_timeout_sec = 10;
2427 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2428 MYLOGE(
2429 "killing dumpstateBoard timed out after %zus, continue and "
2430 "there might be racing in content\n",
2431 killing_timeout_sec);
2432 }
2433}
2434
2435static void DoDumpstateBoardAidl(
2436 const std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal,
2437 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2438 const Dumpstate::BugreportMode bugreport_mode, const size_t timeout_sec) {
2439 MYLOGI("Using IDumpstateDevice AIDL HAL");
2440
2441 const char* descriptor_to_kill;
2442 using DumpstateBoardTask = std::packaged_task<bool()>;
2443 DumpstateBoardTask dumpstate_board_task;
2444 dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode dumpstate_hal_mode =
2445 GetDumpstateHalModeAidl(bugreport_mode);
2446
2447 descriptor_to_kill = dumpstate_hal_aidl::IDumpstateDevice::descriptor;
2448 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal, &dumpstate_fds, dumpstate_hal_mode,
2449 timeout_sec]() -> bool {
2450 auto status = dumpstate_hal->dumpstateBoard(dumpstate_fds, dumpstate_hal_mode, timeout_sec);
2451
2452 if (!status.isOk()) {
2453 MYLOGE("dumpstateBoard failed: %s\n", status.getDescription().c_str());
2454 return false;
2455 }
2456 return true;
2457 });
2458 auto result = dumpstate_board_task.get_future();
2459 std::thread(std::move(dumpstate_board_task)).detach();
2460
2461 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2462 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2463 if (!android::base::SetProperty(
2464 "ctl.interface_restart",
2465 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2466 MYLOGE("Couldn't restart dumpstate HAL\n");
2467 }
2468 }
2469 // Wait some time for init to kill dumpstate vendor HAL
2470 constexpr size_t killing_timeout_sec = 10;
2471 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2472 MYLOGE(
2473 "killing dumpstateBoard timed out after %zus, continue and "
2474 "there might be racing in content\n",
2475 killing_timeout_sec);
2476 }
2477}
2478
2479static std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> GetDumpstateBoardAidlService() {
2480 const std::string aidl_instance_name =
2481 std::string(dumpstate_hal_aidl::IDumpstateDevice::descriptor) + "/default";
2482
2483 if (!AServiceManager_isDeclared(aidl_instance_name.c_str())) {
2484 return nullptr;
2485 }
2486
2487 ndk::SpAIBinder dumpstateBinder(AServiceManager_waitForService(aidl_instance_name.c_str()));
2488
2489 return dumpstate_hal_aidl::IDumpstateDevice::fromBinder(dumpstateBinder);
2490}
2491
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002492void Dumpstate::DumpstateBoard(int out_fd) {
2493 dprintf(out_fd, "========================================================\n");
2494 dprintf(out_fd, "== Board\n");
2495 dprintf(out_fd, "========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08002496
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002497 /*
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002498 * mount debugfs for non-user builds with ro.product.debugfs_restrictions.enabled
Hridya Valsaraju51101602021-04-02 14:32:46 -07002499 * set to true and unmount it after invoking dumpstateBoard_* methods.
2500 * This is to enable debug builds to not have debugfs mounted during runtime.
2501 * It will also ensure that debugfs is only accessed by the dumpstate HAL.
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002502 */
Hridya Valsaraju51101602021-04-02 14:32:46 -07002503 auto mount_debugfs =
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002504 android::base::GetBoolProperty("ro.product.debugfs_restrictions.enabled", false);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002505 if (mount_debugfs) {
2506 RunCommand("mount debugfs", {"mount", "-t", "debugfs", "debugfs", "/sys/kernel/debug"},
2507 AS_ROOT_20);
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002508 RunCommand("chmod debugfs", {"chmod", "0755", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002509 }
2510
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002511 std::vector<std::string> paths;
2512 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07002513 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002514 paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
2515 kDumpstateBoardFiles[i].c_str()));
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002516 remover.emplace_back(android::base::make_scope_guard(
2517 std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002518 }
Jie Song9fbfad02017-06-20 16:29:42 -07002519
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002520 // get dumpstate HAL AIDL implementation
2521 std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal_handle_aidl(
2522 GetDumpstateBoardAidlService());
2523 if (dumpstate_hal_handle_aidl == nullptr) {
2524 MYLOGI("No IDumpstateDevice AIDL implementation\n");
2525 }
2526
2527 // get dumpstate HAL HIDL implementation, only if AIDL HAL implementation not found
2528 sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_handle_hidl_1_0 = nullptr;
2529 if (dumpstate_hal_handle_aidl == nullptr) {
2530 dumpstate_hal_handle_hidl_1_0 = dumpstate_hal_hidl_1_0::IDumpstateDevice::getService();
2531 if (dumpstate_hal_handle_hidl_1_0 == nullptr) {
2532 MYLOGI("No IDumpstateDevice HIDL implementation\n");
2533 }
2534 }
2535
2536 // if neither HIDL nor AIDL implementation found, then return
2537 if (dumpstate_hal_handle_hidl_1_0 == nullptr && dumpstate_hal_handle_aidl == nullptr) {
2538 MYLOGE("Could not find IDumpstateDevice implementation\n");
Wei Wang587eac92018-04-05 12:17:20 -07002539 return;
2540 }
2541
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002542 // this is used to hold the file descriptors and when this variable goes out of scope
2543 // the file descriptors are closed
2544 std::vector<::ndk::ScopedFileDescriptor> dumpstate_fds;
Wei Wang587eac92018-04-05 12:17:20 -07002545
Nandana Dutt5c390032019-03-12 10:52:56 +00002546 // TODO(128270426): Check for consent in between?
Wei Wang587eac92018-04-05 12:17:20 -07002547 for (size_t i = 0; i < paths.size(); i++) {
2548 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
2549
2550 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
2551 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
2552 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
2553 if (fd < 0) {
2554 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
2555 return;
2556 }
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002557
2558 dumpstate_fds.emplace_back(fd.release());
2559 // we call fd.release() here to make sure "fd" does not get closed
2560 // after "fd" goes out of scope after this block.
2561 // "fd" will be closed when "dumpstate_fds" goes out of scope
2562 // i.e. when we exit this function
Wei Wang587eac92018-04-05 12:17:20 -07002563 }
2564
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002565 // Given that bugreport is required to diagnose failures, it's better to set an arbitrary amount
2566 // of timeout for IDumpstateDevice than to block the rest of bugreport. In the timeout case, we
2567 // will kill the HAL and grab whatever it dumped in time.
Michael Eastwood8523ea02022-03-10 16:33:08 -08002568 constexpr size_t timeout_sec = 45;
Wei Wang587eac92018-04-05 12:17:20 -07002569
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002570 if (dumpstate_hal_handle_aidl != nullptr) {
2571 DoDumpstateBoardAidl(dumpstate_hal_handle_aidl, dumpstate_fds, options_->bugreport_mode,
2572 timeout_sec);
2573 } else if (dumpstate_hal_handle_hidl_1_0 != nullptr) {
2574 // run HIDL HAL only if AIDL HAL not found
2575 DoDumpstateBoardHidl(dumpstate_hal_handle_hidl_1_0, dumpstate_fds, options_->bugreport_mode,
2576 timeout_sec);
Wei Wang587eac92018-04-05 12:17:20 -07002577 }
2578
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002579 if (mount_debugfs) {
Hridya Valsaraju51101602021-04-02 14:32:46 -07002580 auto keep_debugfs_mounted =
2581 android::base::GetProperty("persist.dbg.keep_debugfs_mounted", "");
2582 if (keep_debugfs_mounted.empty())
2583 RunCommand("unmount debugfs", {"umount", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002584 }
2585
Wei Wang587eac92018-04-05 12:17:20 -07002586 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
2587 for (size_t i = 0; i < paths.size(); i++) {
2588 struct stat s;
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002589 if (fstat(dumpstate_fds[i].get(), &s) == -1) {
2590 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(), strerror(errno));
Wei Wang587eac92018-04-05 12:17:20 -07002591 file_sizes[i] = -1;
2592 continue;
2593 }
2594 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002595 }
2596
2597 for (size_t i = 0; i < paths.size(); i++) {
2598 if (file_sizes[i] == -1) {
2599 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002600 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002601 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07002602 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002603 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002604 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002605 remover[i].Disable();
2606 EnqueueAddZipEntryAndCleanupIfNeeded(kDumpstateBoardFiles[i], paths[i]);
2607 dprintf(out_fd, "*** See %s entry ***\n", kDumpstateBoardFiles[i].c_str());
Jie Song9fbfad02017-06-20 16:29:42 -07002608 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08002609}
2610
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002611static void ShowUsage() {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002612 fprintf(stderr,
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002613 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o directory] [-p] "
2614 "[-s] [-S] [-q] [-P] [-R] [-L] [-V version]\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002615 " -h: display this help message\n"
2616 " -b: play sound file instead of vibrate, at beginning of job\n"
2617 " -e: play sound file instead of vibrate, at end of job\n"
mhasank2d75c442020-06-11 15:05:25 -07002618 " -o: write to custom directory (only in limited mode)\n"
Abhijeet Kaurbb55a3b2019-06-13 18:07:25 +01002619 " -p: capture screenshot to filename.png\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002620 " -s: write zipped file to control socket (for init)\n"
2621 " -S: write file location to control socket (for init)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002622 " -q: disable vibrate\n"
Abhijeet Kaure370d682019-10-01 16:49:30 +01002623 " -P: send broadcast when started and do progress updates\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002624 " -R: take bugreport in remote mode (shouldn't be used with -P)\n"
Nandana Dutt235864b2019-01-22 12:10:16 +00002625 " -w: start binder service and make it wait for a call to startBugreport\n"
mhasankd451a472020-05-26 18:02:39 -07002626 " -L: output limited information that is safe for submission in feedback reports\n"
Felipe Lemed071c682016-10-20 16:48:00 -07002627 " -v: prints the dumpstate header and exit\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002628}
2629
Wei Liuf87959e2016-08-26 14:51:42 -07002630static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07002631 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07002632}
2633
Felipe Leme1d486fe2016-10-14 18:06:47 -07002634bool Dumpstate::FinishZipFile() {
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002635 // Runs all enqueued adding zip entry and cleanup tasks before finishing the zip file.
2636 if (zip_entry_tasks_) {
2637 zip_entry_tasks_->run(/* do_cancel = */false);
2638 }
2639
Felipe Leme9a523ae2016-10-20 15:10:33 -07002640 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07002641 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07002642 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002643 // Final timestamp
2644 char date[80];
2645 time_t the_real_now_please_stand_up = time(nullptr);
2646 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002647 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002648 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002649
Felipe Leme9a523ae2016-10-20 15:10:33 -07002650 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002651 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08002652 return false;
2653 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07002654 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002655 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08002656 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08002657 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08002658
Felipe Leme0f3fb202016-06-10 17:10:53 -07002659 // Add log file (which contains stderr output) to zip...
2660 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002661 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07002662 MYLOGE("Failed to add dumpstate log to .zip file\n");
2663 return false;
2664 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002665 // TODO: Should truncate the existing file.
2666 // ... and re-open it for further logging.
Nandana Dutta344cb62019-02-22 15:12:35 +00002667 if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
2668 return false;
2669 }
Felipe Leme0f3fb202016-06-10 17:10:53 -07002670 fprintf(stderr, "\n");
2671
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002672 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07002673 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002674 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002675 return false;
2676 }
2677
Felipe Leme1d486fe2016-10-14 18:06:47 -07002678 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
2679 ds.zip_file.reset(nullptr);
2680
Felipe Lemee9d2c542016-11-15 11:48:26 -08002681 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002682 android::os::UnlinkAndLogOnError(tmp_path_);
Felipe Lemec4eee562016-04-21 15:42:55 -07002683
Felipe Leme1e9edc62015-12-21 16:02:13 -08002684 return true;
2685}
Felipe Leme6e01fa62015-11-11 19:35:14 -08002686
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00002687static void SendBroadcast(const std::string& action,
2688 const std::vector<std::string>& args,
2689 int32_t user_id) {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002690 // clang-format off
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00002691 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user",
2692 std::to_string(user_id), "--receiver-foreground",
2693 "--receiver-include-background", "-a", action};
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002694 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08002695
2696 am.insert(am.end(), args.begin(), args.end());
2697
Felipe Leme8d2410e2017-02-08 09:46:08 -08002698 RunCommand("", am,
2699 CommandOptions::WithTimeout(20)
2700 .Log("Sending broadcast: '%s'\n")
2701 .Always()
2702 .DropRoot()
2703 .RedirectStderr()
2704 .Build());
2705}
2706
Felipe Leme35b8cf12017-02-10 15:47:29 -08002707static void Vibrate(int duration_ms) {
2708 // clang-format off
Lais Andrade51156962021-02-22 19:21:35 +00002709 std::vector<std::string> args = {"cmd", "vibrator_manager", "synced", "-f", "-d", "dumpstate",
2710 "oneshot", std::to_string(duration_ms)};
2711 RunCommand("", args,
Felipe Leme35b8cf12017-02-10 15:47:29 -08002712 CommandOptions::WithTimeout(10)
2713 .Log("Vibrate: '%s'\n")
2714 .Always()
2715 .Build());
2716 // clang-format on
2717}
2718
Nandana Dutt979388e2018-11-30 16:48:55 +00002719static void MaybeResolveSymlink(std::string* path) {
2720 std::string resolved_path;
2721 if (android::base::Readlink(*path, &resolved_path)) {
2722 *path = resolved_path;
2723 }
2724}
2725
Nandana Dutt4be45d12018-09-26 15:04:23 +01002726/*
2727 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002728 * and adds the version file. Return false if zip_file could not be open to write.
Nandana Dutt4be45d12018-09-26 15:04:23 +01002729 */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002730static bool PrepareToWriteToFile() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002731 MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2732
Nandana Dutt4be45d12018-09-26 15:04:23 +01002733 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2734 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002735 ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002736 char date[80];
2737 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2738 ds.name_ = date;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002739
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002740 if (ds.options_->telephony_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002741 ds.base_name_ += "-telephony";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002742 } else if (ds.options_->wifi_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002743 ds.base_name_ += "-wifi";
2744 }
2745
Paul Chang0d2aad72020-02-13 20:04:03 +08002746 if (ds.options_->do_screenshot) {
Nandana Dutt9d17b942020-03-26 10:02:59 +00002747 ds.screenshot_path_ = ds.GetPath(ds.CalledByApi() ? "-png.tmp" : ".png");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002748 }
2749 ds.tmp_path_ = ds.GetPath(".tmp");
2750 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2751
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01002752 std::string destination = ds.CalledByApi()
Nandana Dutt54dbd672019-01-11 12:58:05 +00002753 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
Nandana Dutt9a76d202019-01-21 15:56:48 +00002754 : ds.bugreport_internal_dir_.c_str();
Nandana Dutt4be45d12018-09-26 15:04:23 +01002755 MYLOGD(
Nandana Dutt235c6672019-11-14 15:22:32 +00002756 "Bugreport dir: [%s] "
2757 "Base name: [%s] "
2758 "Suffix: [%s] "
2759 "Log path: [%s] "
2760 "Temporary path: [%s] "
2761 "Screenshot path: [%s]\n",
Nandana Dutt9a76d202019-01-21 15:56:48 +00002762 destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2763 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002764
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002765 ds.path_ = ds.GetPath(ds.CalledByApi() ? "-zip.tmp" : ".zip");
2766 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2767 create_parent_dirs(ds.path_.c_str());
2768 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2769 if (ds.zip_file == nullptr) {
2770 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2771 return false;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002772 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002773 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2774 ds.AddTextZipEntry("version.txt", ds.version_);
2775 return true;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002776}
2777
2778/*
Abhijeet Kaure370d682019-10-01 16:49:30 +01002779 * Finalizes writing to the file by zipping the tmp file to the final location,
Nandana Dutt4be45d12018-09-26 15:04:23 +01002780 * printing zipped file status, etc.
2781 */
2782static void FinalizeFile() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002783 bool do_text_file = !ds.FinishZipFile();
2784 if (do_text_file) {
2785 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002786 }
mhasank2d75c442020-06-11 15:05:25 -07002787
2788 std::string final_path = ds.path_;
2789 if (ds.options_->OutputToCustomFile()) {
mhasank3a4cfb42020-06-15 18:06:43 -07002790 final_path = ds.GetPath(ds.options_->out_dir, ".zip");
mhasank2d75c442020-06-11 15:05:25 -07002791 android::os::CopyFileToFile(ds.path_, final_path);
2792 }
2793
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002794 if (ds.options_->stream_to_socket) {
2795 android::os::CopyFileToFd(ds.path_, ds.control_socket_fd_);
2796 } else if (ds.options_->progress_updates_to_socket) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002797 if (do_text_file) {
2798 dprintf(ds.control_socket_fd_,
2799 "FAIL:could not create zip file, check %s "
2800 "for more details\n",
2801 ds.log_path_.c_str());
2802 } else {
mhasank2d75c442020-06-11 15:05:25 -07002803 dprintf(ds.control_socket_fd_, "OK:%s\n", final_path.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002804 }
2805 }
2806}
2807
Nandana Dutt4be45d12018-09-26 15:04:23 +01002808
Nandana Dutt58d72e22018-11-16 10:30:48 +00002809static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2810 switch (mode) {
2811 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2812 return "BUGREPORT_FULL";
2813 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2814 return "BUGREPORT_INTERACTIVE";
2815 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2816 return "BUGREPORT_REMOTE";
2817 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2818 return "BUGREPORT_WEAR";
2819 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2820 return "BUGREPORT_TELEPHONY";
2821 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2822 return "BUGREPORT_WIFI";
Elis Elliott8e401ad2023-08-08 11:18:59 +00002823 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
2824 return "BUGREPORT_ONBOARDING";
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002825 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2826 return "BUGREPORT_DEFAULT";
Nandana Dutt58d72e22018-11-16 10:30:48 +00002827 }
2828}
2829
Steven Leeb573eb82022-11-29 22:31:35 +08002830static bool IsConsentlessBugreportAllowed(const Dumpstate::DumpOptions& options) {
2831 // only BUGREPORT_TELEPHONY does not allow using consentless bugreport
2832 return !options.telephony_only;
2833}
2834
Paul Changf59c2b72020-03-10 02:08:55 +08002835static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options,
2836 bool is_screenshot_requested) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002837 // Modify com.android.shell.BugreportProgressService#isDefaultScreenshotRequired as well for
2838 // default system screenshots.
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002839 options->bugreport_mode = mode;
2840 options->bugreport_mode_string = ModeToString(mode);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002841 switch (mode) {
2842 case Dumpstate::BugreportMode::BUGREPORT_FULL:
Paul Changf59c2b72020-03-10 02:08:55 +08002843 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002844 break;
2845 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002846 // Currently, the dumpstate binder is only used by Shell to update progress.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002847 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002848 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002849 break;
2850 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002851 options->do_vibrate = false;
2852 options->is_remote_mode = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002853 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002854 break;
2855 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
Robert Ginda55ecebd2023-04-03 22:53:13 +00002856 options->do_vibrate = false;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002857 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002858 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002859 break;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002860 // TODO(b/148168577) rename TELEPHONY everywhere to CONNECTIVITY.
Nandana Dutt58d72e22018-11-16 10:30:48 +00002861 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002862 options->telephony_only = true;
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002863 options->do_progress_updates = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002864 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002865 break;
2866 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002867 options->wifi_only = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002868 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002869 break;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002870 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
2871 options->onboarding_only = true;
2872 options->do_screenshot = false;
2873 break;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002874 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2875 break;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002876 }
2877}
2878
Nandana Dutt58d72e22018-11-16 10:30:48 +00002879static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
Nandana Dutt235c6672019-11-14 15:22:32 +00002880 MYLOGI(
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002881 "do_vibrate: %d stream_to_socket: %d progress_updates_to_socket: %d do_screenshot: %d "
Rhed Jao25f50e02020-08-20 00:10:32 +08002882 "is_remote_mode: %d show_header_only: %d telephony_only: %d "
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002883 "wifi_only: %d do_progress_updates: %d fd: %d bugreport_mode: %s "
mhasankd451a472020-05-26 18:02:39 -07002884 "limited_only: %d args: %s\n",
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002885 options.do_vibrate, options.stream_to_socket, options.progress_updates_to_socket,
Paul Chang0d2aad72020-02-13 20:04:03 +08002886 options.do_screenshot, options.is_remote_mode, options.show_header_only,
Rhed Jao25f50e02020-08-20 00:10:32 +08002887 options.telephony_only, options.wifi_only,
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002888 options.do_progress_updates, options.bugreport_fd.get(),
2889 options.bugreport_mode_string.c_str(),
2890 options.limited_only, options.args.c_str());
Nandana Dutt58d72e22018-11-16 10:30:48 +00002891}
2892
Nandana Dutt54dbd672019-01-11 12:58:05 +00002893void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
Kean Mariotti306633e2022-09-05 16:30:47 +00002894 int bugreport_flags,
Nandana Dutt54dbd672019-01-11 12:58:05 +00002895 const android::base::unique_fd& bugreport_fd_in,
Paul Changf59c2b72020-03-10 02:08:55 +08002896 const android::base::unique_fd& screenshot_fd_in,
2897 bool is_screenshot_requested) {
Kean Mariotti306633e2022-09-05 16:30:47 +00002898 this->use_predumped_ui_data = bugreport_flags & BugreportFlag::BUGREPORT_USE_PREDUMPED_UI_DATA;
Gavin Corkerya44686c2022-11-23 18:16:51 +00002899 this->is_consent_deferred = bugreport_flags & BugreportFlag::BUGREPORT_FLAG_DEFER_CONSENT;
Nandana Dutt54dbd672019-01-11 12:58:05 +00002900 // Duplicate the fds because the passed in fds don't outlive the binder transaction.
Todd Frederick621533f2022-03-26 02:54:17 +00002901 bugreport_fd.reset(fcntl(bugreport_fd_in.get(), F_DUPFD_CLOEXEC, 0));
2902 screenshot_fd.reset(fcntl(screenshot_fd_in.get(), F_DUPFD_CLOEXEC, 0));
Nandana Dutt58d72e22018-11-16 10:30:48 +00002903
Paul Changf59c2b72020-03-10 02:08:55 +08002904 SetOptionsFromMode(bugreport_mode, this, is_screenshot_requested);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002905}
2906
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002907Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
2908 RunStatus status = RunStatus::OK;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002909 int c;
mhasankd451a472020-05-26 18:02:39 -07002910 while ((c = getopt(argc, argv, "dho:svqzpLPBRSV:w")) != -1) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002911 switch (c) {
2912 // clang-format off
mhasank3a4cfb42020-06-15 18:06:43 -07002913 case 'o': out_dir = optarg; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002914 case 's': stream_to_socket = true; break;
2915 case 'S': progress_updates_to_socket = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002916 case 'v': show_header_only = true; break;
2917 case 'q': do_vibrate = false; break;
Paul Chang0d2aad72020-02-13 20:04:03 +08002918 case 'p': do_screenshot = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002919 case 'P': do_progress_updates = true; break;
2920 case 'R': is_remote_mode = true; break;
mhasankd451a472020-05-26 18:02:39 -07002921 case 'L': limited_only = true; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002922 case 'V':
2923 case 'd':
2924 case 'z':
2925 // compatibility no-op
2926 break;
Nandana Dutt235864b2019-01-22 12:10:16 +00002927 case 'w':
2928 // This was already processed
2929 break;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002930 case 'h':
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002931 status = RunStatus::HELP;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002932 break;
2933 default:
2934 fprintf(stderr, "Invalid option: %c\n", c);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002935 status = RunStatus::INVALID_INPUT;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002936 break;
2937 // clang-format on
2938 }
2939 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08002940
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002941 for (int i = 0; i < argc; i++) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002942 args += argv[i];
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002943 if (i < argc - 1) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002944 args += " ";
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002945 }
2946 }
2947
2948 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
2949 optind = 1;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002950
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002951 return status;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002952}
2953
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002954bool Dumpstate::DumpOptions::ValidateOptions() const {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002955 if (bugreport_fd.get() != -1 && stream_to_socket) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002956 return false;
2957 }
2958
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002959 if ((progress_updates_to_socket || do_progress_updates) && stream_to_socket) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002960 return false;
2961 }
2962
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002963 if (is_remote_mode && (do_progress_updates || stream_to_socket)) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002964 return false;
2965 }
2966 return true;
2967}
2968
Nandana Dutt197661d2018-11-16 16:40:21 +00002969void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
2970 options_ = std::move(options);
2971}
2972
Abhijeet Kaura407fb82020-03-27 12:51:12 +00002973void Dumpstate::Initialize() {
2974 /* gets the sequential id */
2975 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
2976 id_ = ++last_id;
2977 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
2978}
2979
Nandana Duttd2f5f082019-01-18 17:13:52 +00002980Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
2981 Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
Gavin Corkerya44686c2022-11-23 18:16:51 +00002982 HandleRunStatus(status);
2983 return status;
2984}
2985
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00002986Dumpstate::RunStatus Dumpstate::Retrieve(int32_t calling_uid, const std::string& calling_package,
2987 const bool keep_bugreport_on_retrieval) {
2988 Dumpstate::RunStatus status = RetrieveInternal(calling_uid, calling_package,
2989 keep_bugreport_on_retrieval);
Gavin Corkerya44686c2022-11-23 18:16:51 +00002990 HandleRunStatus(status);
2991 return status;
2992}
2993
2994Dumpstate::RunStatus Dumpstate::RetrieveInternal(int32_t calling_uid,
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00002995 const std::string& calling_package,
2996 const bool keep_bugreport_on_retrieval) {
Gavin Corkerya44686c2022-11-23 18:16:51 +00002997 consent_callback_ = new ConsentCallback();
2998 const String16 incidentcompanion("incidentcompanion");
2999 sp<android::IBinder> ics(
3000 defaultServiceManager()->checkService(incidentcompanion));
3001 android::String16 package(calling_package.c_str());
3002 if (ics != nullptr) {
3003 MYLOGD("Checking user consent via incidentcompanion service\n");
3004 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
3005 calling_uid, package, String16(), String16(),
3006 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
3007 } else {
3008 MYLOGD(
3009 "Unable to check user consent; incidentcompanion service unavailable\n");
3010 return RunStatus::USER_CONSENT_TIMED_OUT;
3011 }
3012 UserConsentResult consent_result = consent_callback_->getResult();
3013 int timeout_ms = 30 * 1000;
3014 while (consent_result == UserConsentResult::UNAVAILABLE &&
3015 consent_callback_->getElapsedTimeMs() < timeout_ms) {
3016 sleep(1);
3017 consent_result = consent_callback_->getResult();
3018 }
3019 if (consent_result == UserConsentResult::DENIED) {
3020 return RunStatus::USER_CONSENT_DENIED;
3021 }
3022 if (consent_result == UserConsentResult::UNAVAILABLE) {
3023 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3024 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3025 consent_callback_.get());
3026 return RunStatus::USER_CONSENT_TIMED_OUT;
3027 }
3028
3029 bool copy_succeeded =
3030 android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003031
3032 if (copy_succeeded && (!android::app::admin::flags::onboarding_bugreport_v2_enabled()
3033 || !keep_bugreport_on_retrieval)) {
3034 android::os::UnlinkAndLogOnError(path_);
Gavin Corkerya44686c2022-11-23 18:16:51 +00003035 }
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003036
Gavin Corkerya44686c2022-11-23 18:16:51 +00003037 return copy_succeeded ? Dumpstate::RunStatus::OK
3038 : Dumpstate::RunStatus::ERROR;
3039}
3040
3041void Dumpstate::HandleRunStatus(Dumpstate::RunStatus status) {
3042 if (listener_ != nullptr) {
Nandana Duttbabf6c72019-01-15 14:11:12 +00003043 switch (status) {
3044 case Dumpstate::RunStatus::OK:
Gavin Corkerya44686c2022-11-23 18:16:51 +00003045 listener_->onFinished(path_.c_str());
Nandana Duttbabf6c72019-01-15 14:11:12 +00003046 break;
3047 case Dumpstate::RunStatus::HELP:
3048 break;
3049 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003050 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00003051 break;
3052 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003053 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
3054 break;
3055 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3056 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
3057 break;
3058 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
3059 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00003060 break;
3061 }
3062 }
Nandana Duttbabf6c72019-01-15 14:11:12 +00003063}
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003064void Dumpstate::Cancel() {
3065 CleanupTmpFiles();
3066 android::os::UnlinkAndLogOnError(log_path_);
3067 for (int i = 0; i < NUM_OF_DUMPS; i++) {
3068 android::os::UnlinkAndLogOnError(ds.bugreport_internal_dir_ + "/" +
3069 kDumpstateBoardFiles[i]);
3070 }
3071 tombstone_data_.clear();
3072 anr_data_.clear();
Andy Hungd62f7e62024-01-11 15:47:52 -08003073 anr_trace_data_.clear();
Woody Lin20767a92022-11-29 15:50:24 +08003074 shutdown_checkpoints_.clear();
Rhed Jao0daac912020-08-21 14:48:20 +08003075
3076 // Instead of shutdown the pool, we delete temporary files directly since
3077 // shutdown blocking the call.
3078 if (dump_pool_) {
3079 dump_pool_->deleteTempFiles();
3080 }
3081 if (zip_entry_tasks_) {
3082 zip_entry_tasks_->run(/*do_cancel =*/ true);
3083 }
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003084}
3085
Kean Mariotti306633e2022-09-05 16:30:47 +00003086void Dumpstate::PreDumpUiData() {
Kean Mariotti853b73a2023-07-27 12:40:30 +00003087 MaybeSnapshotSystemTrace();
Kean Mariotti306633e2022-09-05 16:30:47 +00003088 MaybeSnapshotUiTraces();
3089}
3090
Nandana Dutt979388e2018-11-30 16:48:55 +00003091/*
3092 * Dumps relevant information to a bugreport based on the given options.
3093 *
3094 * The bugreport can be dumped to a file or streamed to a socket.
3095 *
3096 * How dumping to file works:
3097 * stdout is redirected to a temporary file. This will later become the main bugreport entry.
3098 * stderr is redirected a log file.
3099 *
3100 * The temporary bugreport is then populated via printfs, dumping contents of files and
3101 * output of commands to stdout.
3102 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003103 * A bunch of other files and dumps are added to the zip archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00003104 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003105 * The temporary bugreport file and the log file also get added to the archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00003106 *
mhasank2d75c442020-06-11 15:05:25 -07003107 * Bugreports are first generated in a local directory and later copied to the caller's fd
3108 * or directory if supplied.
Nandana Dutt979388e2018-11-30 16:48:55 +00003109 */
Nandana Duttd2f5f082019-01-18 17:13:52 +00003110Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
3111 const std::string& calling_package) {
Rhed Jao5377d792020-07-16 17:37:39 +08003112 DurationReporter duration_reporter("RUN INTERNAL", /* logcat_only = */true);
Nandana Dutt979388e2018-11-30 16:48:55 +00003113 LogDumpOptions(*options_);
Nandana Dutt197661d2018-11-16 16:40:21 +00003114 if (!options_->ValidateOptions()) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00003115 MYLOGE("Invalid options specified\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003116 return RunStatus::INVALID_INPUT;
3117 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003118 /* set as high priority, and protect from OOM killer */
3119 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003120
Felipe Lemed071c682016-10-20 16:48:00 -07003121 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07003122 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003123 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003124 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003125 } else {
3126 /* fallback to kernels <= 2.6.35 */
3127 oom_adj = fopen("/proc/self/oom_adj", "we");
3128 if (oom_adj) {
3129 fputs("-17", oom_adj);
3130 fclose(oom_adj);
3131 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003132 }
3133
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003134 if (version_ == VERSION_DEFAULT) {
3135 version_ = VERSION_CURRENT;
Michal Karpinski4db754f2015-12-11 18:04:32 +00003136 }
3137
Chris Morin5a50d482022-02-01 17:41:18 -08003138 if (version_ != VERSION_CURRENT) {
3139 MYLOGE("invalid version requested ('%s'); supported values are: ('%s', '%s')\n",
3140 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003141 return RunStatus::INVALID_INPUT;
Felipe Lemed071c682016-10-20 16:48:00 -07003142 }
3143
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003144 if (options_->show_header_only) {
3145 PrintHeader();
3146 return RunStatus::OK;
Felipe Lemed071c682016-10-20 16:48:00 -07003147 }
3148
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003149 MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n",
3150 calling_uid, calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003151
Felipe Leme7447d7c2016-11-03 18:12:22 -07003152 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003153 std::string stats_path =
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003154 android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003155 progress_.reset(new Progress(stats_path));
Felipe Leme7447d7c2016-11-03 18:12:22 -07003156
Sahana Raof35ed432019-07-12 10:47:52 +01003157 if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
3158 MYLOGE("Failed to acquire wake lock: %s\n", strerror(errno));
3159 } else {
3160 // Wake lock will be released automatically on process death
3161 MYLOGD("Wake lock acquired.\n");
3162 }
3163
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08003164 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07003165
Felipe Lemef0292972016-11-22 13:57:05 -08003166 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07003167 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
3168 }
3169
Kevin Jeonfa64e642023-07-27 11:36:41 -04003170 if (PropertiesHelper::IsStrictRun()) {
3171 MYLOGI(
3172 "Running on strict-run mode, which has shorter timeouts "
3173 "(to disable, call 'setprop dumpstate.strict_run false')\n");
3174 }
3175
Nandana Dutt235c6672019-11-14 15:22:32 +00003176 MYLOGI("dumpstate info: id=%d, args='%s', bugreport_mode= %s bugreport format version: %s\n",
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00003177 id_, options_->args.c_str(), options_->bugreport_mode_string.c_str(), version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08003178
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003179 do_early_screenshot_ = options_->do_progress_updates;
Felipe Lemee338bf62015-12-07 14:03:50 -08003180
Christopher Ferrised9354f2014-10-01 17:35:01 -07003181 // If we are going to use a socket, do it as early as possible
3182 // to avoid timeouts from bugreport.
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003183 if (options_->stream_to_socket || options_->progress_updates_to_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07003184 MYLOGD("Opening control socket\n");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003185 control_socket_fd_ = open_socket_fn_("dumpstate");
Nandana Dutta344cb62019-02-22 15:12:35 +00003186 if (control_socket_fd_ == -1) {
3187 return ERROR;
3188 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003189 if (options_->progress_updates_to_socket) {
3190 options_->do_progress_updates = 1;
3191 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07003192 }
3193
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003194 if (!PrepareToWriteToFile()) {
3195 return ERROR;
3196 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08003197
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003198 // Interactive, wear & telephony modes are default to true.
3199 // and may enable from cli option or when using control socket
3200 if (options_->do_progress_updates) {
3201 // clang-format off
3202 std::vector<std::string> am_args = {
3203 "--receiver-permission", "android.permission.DUMP",
3204 };
3205 // clang-format on
3206 // Send STARTED broadcast for apps that listen to bugreport generation events
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003207 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED",
3208 am_args, multiuser_get_user_id(calling_uid));
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003209 if (options_->progress_updates_to_socket) {
3210 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08003211 }
3212 }
3213
Nick Kralevichf3599b32016-01-25 15:05:16 -08003214 /* read /proc/cmdline before dropping root */
3215 FILE *cmdline = fopen("/proc/cmdline", "re");
3216 if (cmdline) {
3217 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
3218 fclose(cmdline);
3219 }
3220
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003221 if (options_->do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08003222 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05003223 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003224
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003225 if (zip_file != nullptr) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003226 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
3227 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003228 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08003229 }
3230 }
3231
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003232 int dup_stdout_fd;
3233 int dup_stderr_fd;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003234 // Redirect stderr to log_path_ for debugging.
3235 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
3236 if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
3237 return ERROR;
3238 }
3239 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
3240 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
3241 strerror(errno));
3242 }
Nandana Dutt979388e2018-11-30 16:48:55 +00003243
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003244 // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
3245 // moved into zip file later, if zipping.
3246 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
3247 // TODO: why not write to a file instead of stdout to overcome this problem?
3248 /* TODO: rather than generating a text file now and zipping it later,
3249 it would be more efficient to redirect stdout to the zip entry
3250 directly, but the libziparchive doesn't support that option yet. */
3251 if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
3252 return ERROR;
3253 }
3254 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
3255 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
3256 tmp_path_.c_str(), strerror(errno));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003257 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08003258
3259 // Don't buffer stdout
3260 setvbuf(stdout, nullptr, _IONBF, 0);
3261
Rhed Jao5377d792020-07-16 17:37:39 +08003262 // Enable the parallel run if the client requests to output to a file.
3263 EnableParallelRunIfNeeded();
3264 // Using scope guard to make sure the dump pool can be shut down correctly.
3265 auto scope_guard_to_shutdown_pool = android::base::make_scope_guard([=]() {
3266 ShutdownDumpPool();
3267 });
3268
Felipe Leme608385d2016-02-01 10:35:38 -08003269 // NOTE: there should be no stdout output until now, otherwise it would break the header.
3270 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08003271 // duration is logged into MYLOG instead.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003272 PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003273
Kean Mariotti853b73a2023-07-27 12:40:30 +00003274 bool is_dumpstate_restricted =
3275 options_->telephony_only || options_->wifi_only || options_->limited_only;
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003276 if (!is_dumpstate_restricted) {
3277 // Snapshot the system trace now (if running) to avoid that dumpstate's
3278 // own activity pushes out interesting data from the trace ring buffer.
3279 // The trace file is added to the zip by MaybeAddSystemTraceToZip().
3280 MaybeSnapshotSystemTrace();
Yohei Yukawa95305b32021-03-09 07:54:27 -08003281
Kean Mariotti853b73a2023-07-27 12:40:30 +00003282 // Invoke critical dumpsys to preserve system state, before doing anything else.
3283 RunDumpsysCritical();
3284
Kean Mariotti306633e2022-09-05 16:30:47 +00003285 // Snapshot the UI traces now (if running).
3286 // The trace files will be added to bugreport later.
3287 MaybeSnapshotUiTraces();
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003288 }
Kean Mariotti853b73a2023-07-27 12:40:30 +00003289
3290 MaybeTakeEarlyScreenshot();
Gavin Corkery6968f552020-11-22 18:09:05 +00003291 onUiIntensiveBugreportDumpsFinished(calling_uid);
3292 MaybeCheckUserConsent(calling_uid, calling_package);
3293 if (options_->telephony_only) {
3294 DumpstateTelephonyOnly(calling_package);
3295 } else if (options_->wifi_only) {
3296 DumpstateWifiOnly();
3297 } else if (options_->limited_only) {
3298 DumpstateLimitedOnly();
Elis Elliott8e401ad2023-08-08 11:18:59 +00003299 } else if (options_->onboarding_only) {
3300 DumpstateOnboardingOnly();
Gavin Corkery6968f552020-11-22 18:09:05 +00003301 } else {
Nandana Dutt4be45d12018-09-26 15:04:23 +01003302 // Dump state for the default case. This also drops root.
Jichao Lie89d9c12019-11-21 19:02:51 -08003303 RunStatus s = DumpstateDefaultAfterCritical();
Nandana Dutt5c390032019-03-12 10:52:56 +00003304 if (s != RunStatus::OK) {
Nandana Duttaac6f582019-07-26 14:32:47 +01003305 if (s == RunStatus::USER_CONSENT_DENIED) {
Nandana Dutt5c390032019-03-12 10:52:56 +00003306 HandleUserConsentDenied();
3307 }
3308 return s;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08003309 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07003310 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07003311
Felipe Leme55b42a62015-11-10 17:39:08 -08003312 /* close output if needed */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003313 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003314
Abhijeet Kaure370d682019-10-01 16:49:30 +01003315 // Zip the (now complete) .tmp file within the internal directory.
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003316 ATRACE_BEGIN("FinalizeFile");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003317 FinalizeFile();
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003318 ATRACE_END();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003319
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003320 // Share the final file with the caller if the user has consented or Shell is the caller.
Nandana Duttd2f5f082019-01-18 17:13:52 +00003321 Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
Gavin Corkerya44686c2022-11-23 18:16:51 +00003322 if (CalledByApi() && !options_->is_consent_deferred) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003323 status = CopyBugreportIfUserConsented(calling_uid);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003324 if (status != Dumpstate::RunStatus::OK &&
3325 status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3326 // Do an early return if there were errors. We make an exception for consent
3327 // timing out because it's possible the user got distracted. In this case the
3328 // bugreport is not shared but made available for manual retrieval.
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003329 MYLOGI("User denied consent. Returning\n");
Nandana Duttd2f5f082019-01-18 17:13:52 +00003330 return status;
3331 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003332 if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3333 MYLOGI(
3334 "Did not receive user consent yet."
3335 " Will not copy the bugreport artifacts to caller.\n");
Abhijeet Kaur57627412019-04-17 16:00:09 +01003336 const String16 incidentcompanion("incidentcompanion");
3337 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
3338 if (ics != nullptr) {
3339 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3340 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3341 consent_callback_.get());
3342 } else {
3343 MYLOGD("Unable to cancel user consent; incidentcompanion service unavailable\n");
3344 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003345 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003346 }
3347
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003348 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003349 if (options_->do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09003350 for (int i = 0; i < 3; i++) {
3351 Vibrate(75);
3352 usleep((75 + 50) * 1000);
3353 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003354 }
3355
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003356 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
3357 progress_->GetInitialMax());
3358 progress_->Save();
3359 MYLOGI("done (id %d)\n", id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003360
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003361 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08003362
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003363 if (control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07003364 MYLOGD("Closing control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003365 close(control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07003366 }
3367
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003368 tombstone_data_.clear();
3369 anr_data_.clear();
Andy Hungd62f7e62024-01-11 15:47:52 -08003370 anr_trace_data_.clear();
Woody Lin20767a92022-11-29 15:50:24 +08003371 shutdown_checkpoints_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01003372
Nandana Duttd2f5f082019-01-18 17:13:52 +00003373 return (consent_callback_ != nullptr &&
3374 consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
3375 ? USER_CONSENT_TIMED_OUT
3376 : RunStatus::OK;
3377}
3378
Paul Chang0d2aad72020-02-13 20:04:03 +08003379void Dumpstate::MaybeTakeEarlyScreenshot() {
3380 if (!options_->do_screenshot || !do_early_screenshot_) {
3381 return;
3382 }
3383
3384 TakeScreenshot();
3385}
3386
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003387void Dumpstate::MaybeSnapshotSystemTrace() {
Kean Mariotti853b73a2023-07-27 12:40:30 +00003388 // When capturing traces via bugreport handler (BH), this function will be invoked twice:
3389 // 1) When BH invokes IDumpstate::PreDumpUiData()
3390 // 2) When BH invokes IDumpstate::startBugreport(flags = BUGREPORT_USE_PREDUMPED_UI_DATA)
3391 // In this case we don't want to re-invoke perfetto in step 2.
3392 // In all other standard invocation states, this function is invoked once
3393 // without the flag BUGREPORT_USE_PREDUMPED_UI_DATA.
3394 if (options_->use_predumped_ui_data) {
3395 return;
3396 }
3397
3398 // If a stale file exists already, remove it.
3399 unlink(SYSTEM_TRACE_SNAPSHOT);
3400
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003401 // If a background system trace is happening and is marked as "suitable for
3402 // bugreport" (i.e. bugreport_score > 0 in the trace config), this command
3403 // will stop it and serialize into SYSTEM_TRACE_SNAPSHOT. In the (likely)
3404 // case that no trace is ongoing, this command is a no-op.
3405 // Note: this should not be enqueued as we need to freeze the trace before
3406 // dumpstate starts. Otherwise the trace ring buffers will contain mostly
3407 // the dumpstate's own activity which is irrelevant.
Kean Mariotti853b73a2023-07-27 12:40:30 +00003408 RunCommand("SERIALIZE PERFETTO TRACE", {"perfetto", "--save-for-bugreport"},
3409 CommandOptions::WithTimeout(10).DropRoot().CloseAllFileDescriptorsOnExec().Build());
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003410 // MaybeAddSystemTraceToZip() will take care of copying the trace in the zip
3411 // file in the later stages.
3412}
3413
Kean Mariotti306633e2022-09-05 16:30:47 +00003414void Dumpstate::MaybeSnapshotUiTraces() {
3415 if (PropertiesHelper::IsUserBuild() || options_->use_predumped_ui_data) {
3416 return;
3417 }
Hongwei Wang9ec5c252023-01-24 15:09:59 -08003418
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003419 const std::vector<std::vector<std::string>> dumpTracesForBugReportCommands = {
3420 {"dumpsys", "activity", "service", "SystemUIService", "WMShell", "protolog",
3421 "save-for-bugreport"},
3422 {"dumpsys", "activity", "service", "SystemUIService", "WMShell", "transitions", "tracing",
3423 "save-for-bugreport"},
3424 {"cmd", "input_method", "tracing", "save-for-bugreport"},
3425 {"cmd", "window", "tracing", "save-for-bugreport"},
3426 {"cmd", "window", "shell", "tracing", "save-for-bugreport"},
3427 };
Hongwei Wang39229132023-01-24 15:09:59 -08003428
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003429 for (const auto& command : dumpTracesForBugReportCommands) {
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003430 RunCommand(
3431 // Empty name because it's not intended to be classified as a bugreport section.
3432 // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003433 "", command,
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003434 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
3435 }
Kean Mariotti306633e2022-09-05 16:30:47 +00003436}
3437
3438void Dumpstate::MaybeAddUiTracesToZip() {
3439 if (PropertiesHelper::IsUserBuild()) {
3440 return;
3441 }
3442
3443 ds.AddDir(WMTRACE_DATA_DIR, false);
Yohei Yukawa95305b32021-03-09 07:54:27 -08003444}
3445
Paul Changeb4b4642020-05-28 22:05:47 +08003446void Dumpstate::onUiIntensiveBugreportDumpsFinished(int32_t calling_uid) {
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003447 if (multiuser_get_app_id(calling_uid) == AID_SHELL || !CalledByApi()) {
Paul Changc490e662020-04-11 18:14:09 +08003448 return;
3449 }
3450 if (listener_ != nullptr) {
3451 // Let listener know ui intensive bugreport dumps are finished, then it can do event
3452 // handling if required.
Paul Changeb4b4642020-05-28 22:05:47 +08003453 listener_->onUiIntensiveBugreportDumpsFinished();
Paul Changc490e662020-04-11 18:14:09 +08003454 }
3455}
3456
Jichao Lie89d9c12019-11-21 19:02:51 -08003457void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) {
Gavin Corkerya44686c2022-11-23 18:16:51 +00003458 if (multiuser_get_app_id(calling_uid) == AID_SHELL ||
3459 !CalledByApi() || options_->is_consent_deferred) {
3460 // No need to get consent for shell triggered dumpstates, or not
3461 // through bugreporting API (i.e. no fd to copy back), or when consent
3462 // is deferred.
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003463 return;
3464 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003465 consent_callback_ = new ConsentCallback();
3466 const String16 incidentcompanion("incidentcompanion");
3467 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
Jichao Lie89d9c12019-11-21 19:02:51 -08003468 android::String16 package(calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003469 if (ics != nullptr) {
3470 MYLOGD("Checking user consent via incidentcompanion service\n");
Steven Leeb573eb82022-11-29 22:31:35 +08003471 int flags = 0x1; // IncidentManager.FLAG_CONFIRMATION_DIALOG
3472 if (IsConsentlessBugreportAllowed(*options_)) {
3473 flags |= 0x2; // IncidentManager.FLAG_ALLOW_CONSENTLESS_BUGREPORT
3474 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003475 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
Steven Leeb573eb82022-11-29 22:31:35 +08003476 calling_uid, package, String16(), String16(), flags, consent_callback_.get());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003477 } else {
3478 MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
3479 }
3480}
3481
Nandana Dutt5c390032019-03-12 10:52:56 +00003482bool Dumpstate::IsUserConsentDenied() const {
3483 return ds.consent_callback_ != nullptr &&
3484 ds.consent_callback_->getResult() == UserConsentResult::DENIED;
3485}
3486
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01003487bool Dumpstate::CalledByApi() const {
3488 return ds.options_->bugreport_fd.get() != -1 ? true : false;
3489}
3490
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003491void Dumpstate::CleanupTmpFiles() {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003492 android::os::UnlinkAndLogOnError(tmp_path_);
3493 android::os::UnlinkAndLogOnError(screenshot_path_);
3494 android::os::UnlinkAndLogOnError(path_);
Gavin Corkery789d7a52021-02-24 23:52:35 +00003495 if (dump_traces_path != nullptr) {
3496 android::os::UnlinkAndLogOnError(dump_traces_path);
3497 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003498}
3499
Rhed Jao5377d792020-07-16 17:37:39 +08003500void Dumpstate::EnableParallelRunIfNeeded() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003501 if (!PropertiesHelper::IsParallelRun()) {
Rhed Jao5377d792020-07-16 17:37:39 +08003502 return;
3503 }
3504 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003505 zip_entry_tasks_ = std::make_unique<TaskQueue>();
Rhed Jao5377d792020-07-16 17:37:39 +08003506}
3507
3508void Dumpstate::ShutdownDumpPool() {
3509 if (dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08003510 dump_pool_.reset();
Rhed Jao5377d792020-07-16 17:37:39 +08003511 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003512 if (zip_entry_tasks_) {
3513 zip_entry_tasks_->run(/* do_cancel = */true);
3514 zip_entry_tasks_ = nullptr;
3515 }
3516}
3517
3518void Dumpstate::EnqueueAddZipEntryAndCleanupIfNeeded(const std::string& entry_name,
3519 const std::string& entry_path) {
3520 auto func_add_zip_entry_and_cleanup = [=](bool task_cancelled) {
3521 if (!task_cancelled) {
3522 AddZipEntry(entry_name, entry_path);
3523 }
3524 android::os::UnlinkAndLogOnError(entry_path);
3525 };
3526 if (zip_entry_tasks_) {
3527 // Enqueues AddZipEntryAndCleanup function if the parallel run is enabled.
3528 zip_entry_tasks_->add(func_add_zip_entry_and_cleanup, _1);
3529 } else {
3530 // Invokes AddZipEntryAndCleanup immediately
3531 std::invoke(func_add_zip_entry_and_cleanup, /* task_cancelled = */false);
3532 }
Rhed Jao5377d792020-07-16 17:37:39 +08003533}
3534
Nandana Duttd2f5f082019-01-18 17:13:52 +00003535Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
3536 MYLOGD("User denied consent; deleting files and returning\n");
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003537 CleanupTmpFiles();
Nandana Duttd2f5f082019-01-18 17:13:52 +00003538 return USER_CONSENT_DENIED;
3539}
3540
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003541Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented(int32_t calling_uid) {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003542 // If the caller has asked to copy the bugreport over to their directory, we need explicit
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003543 // user consent (unless the caller is Shell).
3544 UserConsentResult consent_result;
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003545 if (multiuser_get_app_id(calling_uid) == AID_SHELL) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003546 consent_result = UserConsentResult::APPROVED;
3547 } else {
3548 consent_result = consent_callback_->getResult();
3549 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003550 if (consent_result == UserConsentResult::UNAVAILABLE) {
3551 // User has not responded yet.
3552 uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
Hunter Knepshield70610fa2020-01-03 15:27:33 -08003553 // Telephony is a fast report type, particularly on user builds where information may be
3554 // more aggressively limited. To give the user time to read the consent dialog, increase the
3555 // timeout.
3556 uint64_t timeout_ms = options_->telephony_only ? TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS
3557 : USER_CONSENT_TIMEOUT_MS;
3558 if (elapsed_ms < timeout_ms) {
3559 uint delay_seconds = (timeout_ms - elapsed_ms) / 1000;
Nandana Duttd2f5f082019-01-18 17:13:52 +00003560 MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
3561 sleep(delay_seconds);
3562 }
3563 consent_result = consent_callback_->getResult();
3564 }
3565 if (consent_result == UserConsentResult::DENIED) {
3566 // User has explicitly denied sharing with the app. To be safe delete the
3567 // internal bugreport & tmp files.
3568 return HandleUserConsentDenied();
3569 }
3570 if (consent_result == UserConsentResult::APPROVED) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00003571 bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
3572 if (copy_succeeded) {
3573 android::os::UnlinkAndLogOnError(path_);
Abhijeet Kaur9ce94672020-04-01 17:22:36 +01003574 if (options_->do_screenshot &&
3575 options_->screenshot_fd.get() != -1 &&
3576 !options_->is_screenshot_copied) {
3577 copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
3578 options_->screenshot_fd.get());
3579 options_->is_screenshot_copied = copy_succeeded;
3580 if (copy_succeeded) {
3581 android::os::UnlinkAndLogOnError(screenshot_path_);
3582 }
3583 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003584 }
3585 return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
3586 } else if (consent_result == UserConsentResult::UNAVAILABLE) {
3587 // consent_result is still UNAVAILABLE. The user has likely not responded yet.
3588 // Since we do not have user consent to share the bugreport it does not get
3589 // copied over to the calling app but remains in the internal directory from
3590 // where the user can manually pull it.
Paul Changce644212021-05-11 16:06:45 +08003591 std::string final_path = GetPath(".zip");
3592 bool copy_succeeded = android::os::CopyFileToFile(path_, final_path);
3593 if (copy_succeeded) {
3594 android::os::UnlinkAndLogOnError(path_);
3595 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003596 return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
3597 }
3598 // Unknown result; must be a programming error.
3599 MYLOGE("Unknown user consent result:%d\n", consent_result);
3600 return Dumpstate::RunStatus::ERROR;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003601}
3602
Nandana Duttf02564e2019-02-15 15:24:24 +00003603Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003604 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
3605 Dumpstate::RunStatus status = options->Initialize(argc, argv);
3606 if (status == Dumpstate::RunStatus::OK) {
Nandana Duttf02564e2019-02-15 15:24:24 +00003607 SetOptions(std::move(options));
Nandana Duttd2f5f082019-01-18 17:13:52 +00003608 // When directly running dumpstate binary, the output is not expected to be written
3609 // to any external file descriptor.
Nandana Duttf02564e2019-02-15 15:24:24 +00003610 assert(options_->bugreport_fd.get() == -1);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003611
3612 // calling_uid and calling_package are for user consent to share the bugreport with
Abhijeet Kaura407fb82020-03-27 12:51:12 +00003613 // an app; they are irrelevant here because bugreport is triggered via command line.
3614 // Update Last ID before calling Run().
3615 Initialize();
Nikhil Kumarb70622a2023-06-15 15:37:19 +01003616 status = Run(0 /* calling_uid */, "" /* calling_package */);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003617 }
Nandana Duttf02564e2019-02-15 15:24:24 +00003618 return status;
3619}
3620
3621/* Main entry point for dumpstate binary. */
3622int run_main(int argc, char* argv[]) {
3623 Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003624
3625 switch (status) {
3626 case Dumpstate::RunStatus::OK:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003627 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003628 case Dumpstate::RunStatus::HELP:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003629 ShowUsage();
3630 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003631 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003632 fprintf(stderr, "Invalid combination of args\n");
3633 ShowUsage();
3634 exit(1);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003635 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003636 FALLTHROUGH_INTENDED;
3637 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3638 FALLTHROUGH_INTENDED;
3639 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003640 exit(2);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003641 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003642}
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003643
3644// TODO(111441001): Default DumpOptions to sensible values.
3645Dumpstate::Dumpstate(const std::string& version)
3646 : pid_(getpid()),
3647 options_(new Dumpstate::DumpOptions()),
Nandana Dutt402a8392019-06-14 14:25:13 +01003648 last_reported_percent_progress_(0),
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003649 version_(version),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003650 now_(time(nullptr)),
3651 open_socket_fn_(open_socket) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003652}
3653
3654Dumpstate& Dumpstate::GetInstance() {
3655 static Dumpstate singleton_(android::base::GetProperty("dumpstate.version", VERSION_CURRENT));
3656 return singleton_;
3657}
3658
Rhed Jao5377d792020-07-16 17:37:39 +08003659DurationReporter::DurationReporter(const std::string& title, bool logcat_only, bool verbose,
3660 int duration_fd) : title_(title), logcat_only_(logcat_only), verbose_(verbose),
3661 duration_fd_(duration_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003662 if (!title_.empty()) {
3663 started_ = Nanotime();
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003664 if (title_.find("SHOW MAP") == std::string::npos) {
3665 ATRACE_ASYNC_BEGIN(title_.c_str(), 0);
3666 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003667 }
3668}
3669
3670DurationReporter::~DurationReporter() {
3671 if (!title_.empty()) {
3672 float elapsed = (float)(Nanotime() - started_) / NANOS_PER_SEC;
chenqiwuaf8b2d92019-12-12 18:53:51 +08003673 if (elapsed >= .5f || verbose_) {
3674 MYLOGD("Duration of '%s': %.2fs\n", title_.c_str(), elapsed);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003675 }
chenqiwuaf8b2d92019-12-12 18:53:51 +08003676 if (!logcat_only_) {
3677 // Use "Yoda grammar" to make it easier to grep|sort sections.
Rhed Jao5377d792020-07-16 17:37:39 +08003678 dprintf(duration_fd_, "------ %.3fs was the duration of '%s' ------\n",
3679 elapsed, title_.c_str());
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003680 }
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003681 if (title_.find("SHOW MAP") == std::string::npos) {
3682 ATRACE_ASYNC_END(title_.c_str(), 0);
3683 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003684 }
3685}
3686
3687const int32_t Progress::kDefaultMax = 5000;
3688
3689Progress::Progress(const std::string& path) : Progress(Progress::kDefaultMax, 1.1, path) {
3690}
3691
3692Progress::Progress(int32_t initial_max, int32_t progress, float growth_factor)
3693 : Progress(initial_max, growth_factor, "") {
3694 progress_ = progress;
3695}
3696
3697Progress::Progress(int32_t initial_max, float growth_factor, const std::string& path)
3698 : initial_max_(initial_max),
3699 progress_(0),
3700 max_(initial_max),
3701 growth_factor_(growth_factor),
3702 n_runs_(0),
3703 average_max_(0),
3704 path_(path) {
3705 if (!path_.empty()) {
3706 Load();
3707 }
3708}
3709
3710void Progress::Load() {
3711 MYLOGD("Loading stats from %s\n", path_.c_str());
3712 std::string content;
3713 if (!android::base::ReadFileToString(path_, &content)) {
3714 MYLOGI("Could not read stats from %s; using max of %d\n", path_.c_str(), max_);
3715 return;
3716 }
3717 if (content.empty()) {
3718 MYLOGE("No stats (empty file) on %s; using max of %d\n", path_.c_str(), max_);
3719 return;
3720 }
3721 std::vector<std::string> lines = android::base::Split(content, "\n");
3722
3723 if (lines.size() < 1) {
3724 MYLOGE("Invalid stats on file %s: not enough lines (%d). Using max of %d\n", path_.c_str(),
3725 (int)lines.size(), max_);
3726 return;
3727 }
3728 char* ptr;
3729 n_runs_ = strtol(lines[0].c_str(), &ptr, 10);
3730 average_max_ = strtol(ptr, nullptr, 10);
3731 if (n_runs_ <= 0 || average_max_ <= 0 || n_runs_ > STATS_MAX_N_RUNS ||
3732 average_max_ > STATS_MAX_AVERAGE) {
3733 MYLOGE("Invalid stats line on file %s: %s\n", path_.c_str(), lines[0].c_str());
3734 initial_max_ = Progress::kDefaultMax;
3735 } else {
3736 initial_max_ = average_max_;
3737 }
3738 max_ = initial_max_;
3739
3740 MYLOGI("Average max progress: %d in %d runs; estimated max: %d\n", average_max_, n_runs_, max_);
3741}
3742
3743void Progress::Save() {
3744 int32_t total = n_runs_ * average_max_ + progress_;
3745 int32_t runs = n_runs_ + 1;
3746 int32_t average = floor(((float)total) / runs);
3747 MYLOGI("Saving stats (total=%d, runs=%d, average=%d) on %s\n", total, runs, average,
3748 path_.c_str());
3749 if (path_.empty()) {
3750 return;
3751 }
3752
3753 std::string content = android::base::StringPrintf("%d %d\n", runs, average);
3754 if (!android::base::WriteStringToFile(content, path_)) {
3755 MYLOGE("Could not save stats on %s\n", path_.c_str());
3756 }
3757}
3758
3759int32_t Progress::Get() const {
3760 return progress_;
3761}
3762
3763bool Progress::Inc(int32_t delta_sec) {
3764 bool changed = false;
3765 if (delta_sec >= 0) {
3766 progress_ += delta_sec;
3767 if (progress_ > max_) {
3768 int32_t old_max = max_;
3769 max_ = floor((float)progress_ * growth_factor_);
3770 MYLOGD("Adjusting max progress from %d to %d\n", old_max, max_);
3771 changed = true;
3772 }
3773 }
3774 return changed;
3775}
3776
3777int32_t Progress::GetMax() const {
3778 return max_;
3779}
3780
3781int32_t Progress::GetInitialMax() const {
3782 return initial_max_;
3783}
3784
3785void Progress::Dump(int fd, const std::string& prefix) const {
3786 const char* pr = prefix.c_str();
3787 dprintf(fd, "%sprogress: %d\n", pr, progress_);
3788 dprintf(fd, "%smax: %d\n", pr, max_);
3789 dprintf(fd, "%sinitial_max: %d\n", pr, initial_max_);
3790 dprintf(fd, "%sgrowth_factor: %0.2f\n", pr, growth_factor_);
3791 dprintf(fd, "%spath: %s\n", pr, path_.c_str());
3792 dprintf(fd, "%sn_runs: %d\n", pr, n_runs_);
3793 dprintf(fd, "%saverage_max: %d\n", pr, average_max_);
3794}
3795
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003796std::string Dumpstate::GetPath(const std::string& suffix) const {
3797 return GetPath(bugreport_internal_dir_, suffix);
3798}
3799
3800std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
3801 return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
3802 name_.c_str(), suffix.c_str());
3803}
3804
3805void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
3806 progress_ = std::move(progress);
3807}
3808
3809void for_each_userid(void (*func)(int), const char *header) {
3810 std::string title = header == nullptr ? "for_each_userid" : android::base::StringPrintf(
3811 "for_each_userid(%s)", header);
3812 DurationReporter duration_reporter(title);
3813 if (PropertiesHelper::IsDryRun()) return;
3814
3815 DIR *d;
3816 struct dirent *de;
3817
3818 if (header) printf("\n------ %s ------\n", header);
3819 func(0);
3820
3821 if (!(d = opendir("/data/system/users"))) {
3822 printf("Failed to open /data/system/users (%s)\n", strerror(errno));
3823 return;
3824 }
3825
3826 while ((de = readdir(d))) {
3827 int userid;
3828 if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
3829 continue;
3830 }
3831 func(userid);
3832 }
3833
3834 closedir(d);
3835}
3836
3837static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
3838 DIR *d;
3839 struct dirent *de;
3840
3841 if (!(d = opendir("/proc"))) {
3842 printf("Failed to open /proc (%s)\n", strerror(errno));
3843 return;
3844 }
3845
3846 if (header) printf("\n------ %s ------\n", header);
3847 while ((de = readdir(d))) {
3848 if (ds.IsUserConsentDenied()) {
3849 MYLOGE(
3850 "Returning early because user denied consent to share bugreport with calling app.");
3851 closedir(d);
3852 return;
3853 }
3854 int pid;
3855 int fd;
3856 char cmdpath[255];
3857 char cmdline[255];
3858
3859 if (!(pid = atoi(de->d_name))) {
3860 continue;
3861 }
3862
3863 memset(cmdline, 0, sizeof(cmdline));
3864
3865 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
3866 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3867 TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
3868 close(fd);
3869 if (cmdline[0]) {
3870 helper(pid, cmdline, arg);
3871 continue;
3872 }
3873 }
3874
3875 // if no cmdline, a kernel thread has comm
3876 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
3877 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3878 TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
3879 close(fd);
3880 if (cmdline[1]) {
3881 cmdline[0] = '[';
3882 size_t len = strcspn(cmdline, "\f\b\r\n");
3883 cmdline[len] = ']';
3884 cmdline[len+1] = '\0';
3885 }
3886 }
3887 if (!cmdline[0]) {
3888 strcpy(cmdline, "N/A");
3889 }
3890 helper(pid, cmdline, arg);
3891 }
3892
3893 closedir(d);
3894}
3895
3896static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
3897 for_each_pid_func *func = (for_each_pid_func*) arg;
3898 func(pid, cmdline);
3899}
3900
3901void for_each_pid(for_each_pid_func func, const char *header) {
3902 std::string title = header == nullptr ? "for_each_pid"
3903 : android::base::StringPrintf("for_each_pid(%s)", header);
3904 DurationReporter duration_reporter(title);
3905 if (PropertiesHelper::IsDryRun()) return;
3906
3907 __for_each_pid(for_each_pid_helper, header, (void *) func);
3908}
3909
3910static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
3911 DIR *d;
3912 struct dirent *de;
3913 char taskpath[255];
3914 for_each_tid_func *func = (for_each_tid_func *) arg;
3915
3916 snprintf(taskpath, sizeof(taskpath), "/proc/%d/task", pid);
3917
3918 if (!(d = opendir(taskpath))) {
3919 printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
3920 return;
3921 }
3922
3923 func(pid, pid, cmdline);
3924
3925 while ((de = readdir(d))) {
3926 if (ds.IsUserConsentDenied()) {
3927 MYLOGE(
3928 "Returning early because user denied consent to share bugreport with calling app.");
3929 closedir(d);
3930 return;
3931 }
3932 int tid;
3933 int fd;
3934 char commpath[255];
3935 char comm[255];
3936
3937 if (!(tid = atoi(de->d_name))) {
3938 continue;
3939 }
3940
3941 if (tid == pid)
3942 continue;
3943
3944 snprintf(commpath, sizeof(commpath), "/proc/%d/comm", tid);
3945 memset(comm, 0, sizeof(comm));
3946 if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
3947 strcpy(comm, "N/A");
3948 } else {
3949 char *c;
3950 TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
3951 close(fd);
3952
3953 c = strrchr(comm, '\n');
3954 if (c) {
3955 *c = '\0';
3956 }
3957 }
3958 func(pid, tid, comm);
3959 }
3960
3961 closedir(d);
3962}
3963
3964void for_each_tid(for_each_tid_func func, const char *header) {
3965 std::string title = header == nullptr ? "for_each_tid"
3966 : android::base::StringPrintf("for_each_tid(%s)", header);
3967 DurationReporter duration_reporter(title);
3968
3969 if (PropertiesHelper::IsDryRun()) return;
3970
3971 __for_each_pid(for_each_tid_helper, header, (void *) func);
3972}
3973
3974void show_wchan(int pid, int tid, const char *name) {
3975 if (PropertiesHelper::IsDryRun()) return;
3976
3977 char path[255];
3978 char buffer[255];
3979 int fd, ret, save_errno;
3980 char name_buffer[255];
3981
3982 memset(buffer, 0, sizeof(buffer));
3983
3984 snprintf(path, sizeof(path), "/proc/%d/wchan", tid);
3985 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
3986 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
3987 return;
3988 }
3989
3990 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3991 save_errno = errno;
3992 close(fd);
3993
3994 if (ret < 0) {
3995 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
3996 return;
3997 }
3998
3999 snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
4000 pid == tid ? 0 : 3, "", name);
4001
4002 printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
4003
4004 return;
4005}
4006
4007// print time in centiseconds
4008static void snprcent(char *buffer, size_t len, size_t spc,
4009 unsigned long long time) {
4010 static long hz; // cache discovered hz
4011
4012 if (hz <= 0) {
4013 hz = sysconf(_SC_CLK_TCK);
4014 if (hz <= 0) {
4015 hz = 1000;
4016 }
4017 }
4018
4019 // convert to centiseconds
4020 time = (time * 100 + (hz / 2)) / hz;
4021
4022 char str[16];
4023
4024 snprintf(str, sizeof(str), " %llu.%02u",
4025 time / 100, (unsigned)(time % 100));
4026 size_t offset = strlen(buffer);
4027 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
4028 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
4029}
4030
4031// print permille as a percent
4032static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
4033 char str[16];
4034
4035 snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
4036 size_t offset = strlen(buffer);
4037 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
4038 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
4039}
4040
4041void show_showtime(int pid, const char *name) {
4042 if (PropertiesHelper::IsDryRun()) return;
4043
4044 char path[255];
4045 char buffer[1023];
4046 int fd, ret, save_errno;
4047
4048 memset(buffer, 0, sizeof(buffer));
4049
4050 snprintf(path, sizeof(path), "/proc/%d/stat", pid);
4051 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
4052 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
4053 return;
4054 }
4055
4056 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
4057 save_errno = errno;
4058 close(fd);
4059
4060 if (ret < 0) {
4061 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
4062 return;
4063 }
4064
4065 // field 14 is utime
4066 // field 15 is stime
4067 // field 42 is iotime
4068 unsigned long long utime = 0, stime = 0, iotime = 0;
4069 if (sscanf(buffer,
4070 "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
4071 "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
4072 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
4073 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
4074 &utime, &stime, &iotime) != 3) {
4075 return;
4076 }
4077
4078 unsigned long long total = utime + stime;
4079 if (!total) {
4080 return;
4081 }
4082
4083 unsigned permille = (iotime * 1000 + (total / 2)) / total;
4084 if (permille > 1000) {
4085 permille = 1000;
4086 }
4087
4088 // try to beautify and stabilize columns at <80 characters
4089 snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
4090 if ((name[0] != '[') || utime) {
4091 snprcent(buffer, sizeof(buffer), 57, utime);
4092 }
4093 snprcent(buffer, sizeof(buffer), 65, stime);
4094 if ((name[0] != '[') || iotime) {
4095 snprcent(buffer, sizeof(buffer), 73, iotime);
4096 }
4097 if (iotime) {
4098 snprdec(buffer, sizeof(buffer), 79, permille);
4099 }
4100 puts(buffer); // adds a trailing newline
4101
4102 return;
4103}
4104
4105void do_dmesg() {
4106 const char *title = "KERNEL LOG (dmesg)";
4107 DurationReporter duration_reporter(title);
4108 printf("------ %s ------\n", title);
4109
4110 if (PropertiesHelper::IsDryRun()) return;
4111
4112 /* Get size of kernel buffer */
4113 int size = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
4114 if (size <= 0) {
4115 printf("Unexpected klogctl return value: %d\n\n", size);
4116 return;
4117 }
4118 char *buf = (char *) malloc(size + 1);
4119 if (buf == nullptr) {
4120 printf("memory allocation failed\n\n");
4121 return;
4122 }
4123 int retval = klogctl(KLOG_READ_ALL, buf, size);
4124 if (retval < 0) {
4125 printf("klogctl failure\n\n");
4126 free(buf);
4127 return;
4128 }
4129 buf[retval] = '\0';
4130 printf("%s\n\n", buf);
4131 free(buf);
4132 return;
4133}
4134
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004135int Dumpstate::DumpFile(const std::string& title, const std::string& path) {
4136 DurationReporter duration_reporter(title);
4137
4138 int status = DumpFileToFd(STDOUT_FILENO, title, path);
4139
4140 UpdateProgress(WEIGHT_FILE);
4141
4142 return status;
4143}
4144
4145int read_file_as_long(const char *path, long int *output) {
luoqiangwei15fcf2022024-03-07 15:29:20 +08004146 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
4147 if (fd.get() < 0) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004148 int err = errno;
4149 MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
4150 return -1;
4151 }
4152 char buffer[50];
luoqiangwei15fcf2022024-03-07 15:29:20 +08004153 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer, sizeof(buffer)));
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004154 if (bytes_read == -1) {
4155 MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
4156 return -2;
4157 }
4158 if (bytes_read == 0) {
4159 MYLOGE("File %s is empty\n", path);
4160 return -3;
4161 }
4162 *output = atoi(buffer);
4163 return 0;
4164}
4165
4166/* calls skip to gate calling dump_from_fd recursively
4167 * in the specified directory. dump_from_fd defaults to
4168 * dump_file_from_fd above when set to NULL. skip defaults
4169 * to false when set to NULL. dump_from_fd will always be
4170 * called with title NULL.
4171 */
4172int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
4173 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4174 DurationReporter duration_reporter(title);
4175 DIR *dirp;
4176 struct dirent *d;
4177 char *newpath = nullptr;
4178 const char *slash = "/";
4179 int retval = 0;
4180
4181 if (!title.empty()) {
4182 printf("------ %s (%s) ------\n", title.c_str(), dir);
4183 }
4184 if (PropertiesHelper::IsDryRun()) return 0;
4185
4186 if (dir[strlen(dir) - 1] == '/') {
4187 ++slash;
4188 }
4189 dirp = opendir(dir);
4190 if (dirp == nullptr) {
4191 retval = -errno;
4192 MYLOGE("%s: %s\n", dir, strerror(errno));
4193 return retval;
4194 }
4195
4196 if (!dump_from_fd) {
4197 dump_from_fd = dump_file_from_fd;
4198 }
4199 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4200 if ((d->d_name[0] == '.')
4201 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4202 || (d->d_name[1] == '\0'))) {
4203 continue;
4204 }
4205 asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
4206 (d->d_type == DT_DIR) ? "/" : "");
4207 if (!newpath) {
4208 retval = -errno;
4209 continue;
4210 }
4211 if (skip && (*skip)(newpath)) {
4212 continue;
4213 }
4214 if (d->d_type == DT_DIR) {
4215 int ret = dump_files("", newpath, skip, dump_from_fd);
4216 if (ret < 0) {
4217 retval = ret;
4218 }
4219 continue;
4220 }
4221 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
4222 if (fd.get() < 0) {
4223 retval = -1;
4224 printf("*** %s: %s\n", newpath, strerror(errno));
4225 continue;
4226 }
4227 (*dump_from_fd)(nullptr, newpath, fd.get());
4228 }
4229 closedir(dirp);
4230 if (!title.empty()) {
4231 printf("\n");
4232 }
4233 return retval;
4234}
4235
4236/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
4237 * it's possible to avoid issues where opening the file itself can get
4238 * stuck.
4239 */
4240int dump_file_from_fd(const char *title, const char *path, int fd) {
4241 if (PropertiesHelper::IsDryRun()) return 0;
4242
4243 int flags = fcntl(fd, F_GETFL);
4244 if (flags == -1) {
4245 printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
4246 return -1;
4247 } else if (!(flags & O_NONBLOCK)) {
4248 printf("*** %s: fd must have O_NONBLOCK set.\n", path);
4249 return -1;
4250 }
4251 return DumpFileFromFdToFd(title, path, fd, STDOUT_FILENO, PropertiesHelper::IsDryRun());
4252}
4253
4254int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004255 const CommandOptions& options, bool verbose_duration, int out_fd) {
4256 DurationReporter duration_reporter(title, false /* logcat_only */,
4257 verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004258
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004259 int status = RunCommandToFd(out_fd, title, full_command, options);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004260
4261 /* TODO: for now we're simplifying the progress calculation by using the
4262 * timeout as the weight. It's a good approximation for most cases, except when calling dumpsys,
4263 * where its weight should be much higher proportionally to its timeout.
4264 * Ideally, it should use a options.EstimatedDuration() instead...*/
4265 UpdateProgress(options.Timeout());
4266
4267 return status;
4268}
4269
4270void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
Rhed Jaoe017f982020-07-21 17:58:41 +08004271 const CommandOptions& options, long dumpsysTimeoutMs, int out_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004272 long timeout_ms = dumpsysTimeoutMs > 0 ? dumpsysTimeoutMs : options.TimeoutInMs();
4273 std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-T", std::to_string(timeout_ms)};
4274 dumpsys.insert(dumpsys.end(), dumpsys_args.begin(), dumpsys_args.end());
Rhed Jaoe017f982020-07-21 17:58:41 +08004275 RunCommand(title, dumpsys, options, false, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004276}
4277
Dieter Hsu105ad0c2020-09-29 15:23:33 +08004278static int open_socket(const char* service) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004279 int s = android_get_control_socket(service);
4280 if (s < 0) {
4281 MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
4282 return -1;
4283 }
4284 fcntl(s, F_SETFD, FD_CLOEXEC);
4285
4286 // Set backlog to 0 to make sure that queue size will be minimum.
4287 // In Linux, because the minimum queue will be 1, connect() will be blocked
4288 // if the other clients already called connect() and the connection request was not accepted.
4289 if (listen(s, 0) < 0) {
4290 MYLOGE("listen(control socket): %s\n", strerror(errno));
4291 return -1;
4292 }
4293
4294 struct sockaddr addr;
4295 socklen_t alen = sizeof(addr);
Abhijeet Kaur2113cae2019-09-13 09:24:15 +01004296 int fd = accept4(s, &addr, &alen, SOCK_CLOEXEC);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004297
4298 // Close socket just after accept(), to make sure that connect() by client will get error
4299 // when the socket is used by the other services.
4300 // There is still a race condition possibility between accept and close, but there is no way
4301 // to close-on-accept atomically.
4302 // See detail; b/123306389#comment25
4303 close(s);
4304
4305 if (fd < 0) {
4306 MYLOGE("accept(control socket): %s\n", strerror(errno));
4307 return -1;
4308 }
4309
4310 return fd;
4311}
4312
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004313// TODO: should call is_valid_output_file and/or be merged into it.
4314void create_parent_dirs(const char *path) {
4315 char *chp = const_cast<char *> (path);
4316
4317 /* skip initial slash */
4318 if (chp[0] == '/')
4319 chp++;
4320
4321 /* create leading directories, if necessary */
4322 struct stat dir_stat;
4323 while (chp && chp[0]) {
4324 chp = strchr(chp, '/');
4325 if (chp) {
4326 *chp = 0;
4327 if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
4328 MYLOGI("Creating directory %s\n", path);
4329 if (mkdir(path, 0770)) { /* drwxrwx--- */
4330 MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
4331 } else if (chown(path, AID_SHELL, AID_SHELL)) {
4332 MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
4333 }
4334 }
4335 *chp++ = '/';
4336 }
4337 }
4338}
4339
4340bool _redirect_to_file(FILE* redirect, char* path, int truncate_flag) {
4341 create_parent_dirs(path);
4342
4343 int fd = TEMP_FAILURE_RETRY(open(path,
4344 O_WRONLY | O_CREAT | truncate_flag | O_CLOEXEC | O_NOFOLLOW,
4345 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
4346 if (fd < 0) {
4347 MYLOGE("%s: %s\n", path, strerror(errno));
4348 return false;
4349 }
4350
4351 TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
4352 close(fd);
4353 return true;
4354}
4355
4356bool redirect_to_file(FILE* redirect, char* path) {
4357 return _redirect_to_file(redirect, path, O_TRUNC);
4358}
4359
4360bool redirect_to_existing_file(FILE* redirect, char* path) {
4361 return _redirect_to_file(redirect, path, O_APPEND);
4362}
4363
4364void dump_route_tables() {
4365 DurationReporter duration_reporter("DUMP ROUTE TABLES");
4366 if (PropertiesHelper::IsDryRun()) return;
4367 const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
4368 ds.DumpFile("RT_TABLES", RT_TABLES_PATH);
4369 FILE* fp = fopen(RT_TABLES_PATH, "re");
4370 if (!fp) {
4371 printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
4372 return;
4373 }
4374 char table[16];
4375 // Each line has an integer (the table number), a space, and a string (the table name). We only
4376 // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
4377 // Add a fixed max limit so this doesn't go awry.
4378 for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
4379 RunCommand("ROUTE TABLE IPv4", {"ip", "-4", "route", "show", "table", table});
4380 RunCommand("ROUTE TABLE IPv6", {"ip", "-6", "route", "show", "table", table});
4381 }
4382 fclose(fp);
4383}
4384
Li Li830179f2022-01-04 12:53:29 -08004385void dump_frozen_cgroupfs(const char *dir, int level,
4386 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4387 DIR *dirp;
4388 struct dirent *d;
4389 char *newpath = nullptr;
4390
4391 dirp = opendir(dir);
4392 if (dirp == nullptr) {
4393 MYLOGE("%s: %s\n", dir, strerror(errno));
4394 return;
4395 }
4396
4397 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4398 if ((d->d_name[0] == '.')
4399 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4400 || (d->d_name[1] == '\0'))) {
4401 continue;
4402 }
4403 if (d->d_type == DT_DIR) {
4404 asprintf(&newpath, "%s/%s/", dir, d->d_name);
4405 if (!newpath) {
4406 continue;
4407 }
4408 if (level == 0 && !strncmp(d->d_name, "uid_", 4)) {
4409 dump_frozen_cgroupfs(newpath, 1, dump_from_fd);
4410 } else if (level == 1 && !strncmp(d->d_name, "pid_", 4)) {
4411 char *freezer = nullptr;
4412 asprintf(&freezer, "%s/%s", newpath, "cgroup.freeze");
4413 if (freezer) {
4414 FILE* fp = fopen(freezer, "r");
4415 if (fp != NULL) {
4416 int frozen;
4417 fscanf(fp, "%d", &frozen);
4418 if (frozen > 0) {
4419 dump_files("", newpath, skip_none, dump_from_fd);
4420 }
4421 fclose(fp);
4422 }
4423 free(freezer);
4424 }
4425 }
4426 }
4427 }
4428 closedir(dirp);
4429}
4430
4431void dump_frozen_cgroupfs() {
Li Li830179f2022-01-04 12:53:29 -08004432 MYLOGD("Adding frozen processes from %s\n", CGROUPFS_DIR);
4433 DurationReporter duration_reporter("FROZEN CGROUPFS");
4434 if (PropertiesHelper::IsDryRun()) return;
4435 dump_frozen_cgroupfs(CGROUPFS_DIR, 0, _add_file_from_fd);
4436}
4437
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004438void Dumpstate::UpdateProgress(int32_t delta_sec) {
4439 if (progress_ == nullptr) {
4440 MYLOGE("UpdateProgress: progress_ not set\n");
4441 return;
4442 }
Rhed Jaobf63d8a2020-07-21 15:42:55 +08004443 // This function updates progress related members of the dumpstate and reports
4444 // progress percentage to the bugreport client. Since it could be called by
4445 // different dump tasks at the same time if the parallel run is enabled, a
4446 // mutex lock is necessary here to synchronize the call.
4447 std::lock_guard<std::recursive_mutex> lock(mutex_);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004448
4449 // Always update progess so stats can be tuned...
Nandana Dutt402a8392019-06-14 14:25:13 +01004450 progress_->Inc(delta_sec);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004451
4452 // ...but only notifiy listeners when necessary.
4453 if (!options_->do_progress_updates) return;
4454
4455 int progress = progress_->Get();
4456 int max = progress_->GetMax();
Nandana Dutt402a8392019-06-14 14:25:13 +01004457 int percent = 100 * progress / max;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004458
Nandana Dutt402a8392019-06-14 14:25:13 +01004459 if (last_reported_percent_progress_ > 0 && percent <= last_reported_percent_progress_) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004460 return;
4461 }
Nandana Dutt402a8392019-06-14 14:25:13 +01004462 last_reported_percent_progress_ = percent;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004463
4464 if (control_socket_fd_ >= 0) {
4465 dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
4466 fsync(control_socket_fd_);
4467 }
4468
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004469 if (listener_ != nullptr) {
Nandana Dutt235c6672019-11-14 15:22:32 +00004470 if (percent % 10 == 0) {
4471 // We don't want to spam logcat, so only log multiples of 10.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004472 MYLOGD("Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004473 } else {
4474 // stderr is ignored on normal invocations, but useful when calling
4475 // /system/bin/dumpstate directly for debuggging.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004476 fprintf(stderr, "Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004477 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004478
4479 listener_->onProgress(percent);
4480 }
4481}
4482
4483void Dumpstate::TakeScreenshot(const std::string& path) {
4484 const std::string& real_path = path.empty() ? screenshot_path_ : path;
4485 int status =
4486 RunCommand("", {"/system/bin/screencap", "-p", real_path},
4487 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
4488 if (status == 0) {
4489 MYLOGD("Screenshot saved on %s\n", real_path.c_str());
4490 } else {
4491 MYLOGE("Failed to take screenshot on %s\n", real_path.c_str());
4492 }
Paul Chang0d2aad72020-02-13 20:04:03 +08004493 if (listener_ != nullptr) {
4494 // Show a visual indication to indicate screenshot is taken via
4495 // IDumpstateListener.onScreenshotTaken()
4496 listener_->onScreenshotTaken(status == 0);
4497 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004498}
4499
4500bool is_dir(const char* pathname) {
4501 struct stat info;
4502 if (stat(pathname, &info) == -1) {
4503 return false;
4504 }
4505 return S_ISDIR(info.st_mode);
4506}
4507
4508time_t get_mtime(int fd, time_t default_mtime) {
4509 struct stat info;
4510 if (fstat(fd, &info) == -1) {
4511 return default_mtime;
4512 }
4513 return info.st_mtime;
4514}