blob: 522442f4ebcad8f91f711fc6bfd829394ea4dcc0 [file] [log] [blame]
Colin Crossf45fa6b2012-03-26 12:38:26 -07001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Felipe Lemef0292972016-11-22 13:57:05 -080016
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070017#define LOG_TAG "dumpstate"
Kevin Jeon2c02e8e2022-07-07 21:45:17 +000018#define ATRACE_TAG ATRACE_TAG_ALWAYS
Colin Crossf45fa6b2012-03-26 12:38:26 -070019
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -070020#include <dirent.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070021#include <errno.h>
22#include <fcntl.h>
Nikita Ioffea325a572019-05-16 19:49:47 +010023#include <inttypes.h>
Felipe Lemead5f6c42015-11-30 14:26:46 -080024#include <libgen.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070025#include <limits.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010026#include <math.h>
27#include <poll.h>
Mark Salyzyn8f37aa52015-06-12 12:28:24 -070028#include <stdbool.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070029#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -070032#include <sys/mount.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080033#include <sys/poll.h>
Christopher Ferris7dc7f322014-07-22 16:08:19 -070034#include <sys/prctl.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070035#include <sys/resource.h>
36#include <sys/stat.h>
37#include <sys/time.h>
38#include <sys/wait.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010039#include <signal.h>
40#include <stdarg.h>
41#include <string.h>
42#include <sys/capability.h>
43#include <sys/inotify.h>
44#include <sys/klog.h>
45#include <time.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070046#include <unistd.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070047
48#include <chrono>
Hridya Valsarajuac582cd2019-08-05 15:39:54 -070049#include <cmath>
Abhijeet Kaurd3cca0d2019-03-25 12:04:16 +000050#include <fstream>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070051#include <functional>
52#include <future>
Narayan Kamath8f788292017-05-25 13:20:39 +010053#include <memory>
Hridya Valsarajuac582cd2019-08-05 15:39:54 -070054#include <numeric>
Narayan Kamath8f788292017-05-25 13:20:39 +010055#include <regex>
56#include <set>
57#include <string>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070058#include <utility>
Narayan Kamath8f788292017-05-25 13:20:39 +010059#include <vector>
Colin Crossf45fa6b2012-03-26 12:38:26 -070060
Kedar Chitnis9fd8c052021-11-16 09:09:22 +000061#include <aidl/android/hardware/dumpstate/IDumpstateDevice.h>
Felipe Leme96c2bbb2016-09-26 09:21:21 -070062#include <android-base/file.h>
63#include <android-base/properties.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070064#include <android-base/scopeguard.h>
Elliott Hughes9dc117c2015-12-07 14:21:50 -080065#include <android-base/stringprintf.h>
Naveen Kalla058e1e82016-10-19 21:38:44 -070066#include <android-base/strings.h>
Andreas Gampeaff68432016-07-18 18:01:27 -070067#include <android-base/unique_fd.h>
Kedar Chitnis9fd8c052021-11-16 09:09:22 +000068#include <android/binder_manager.h>
69#include <android/binder_process.h>
Nikita Ioffea325a572019-05-16 19:49:47 +010070#include <android/content/pm/IPackageManagerNative.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080071#include <android/hardware/dumpstate/1.0/IDumpstateDevice.h>
Hunter Knepshield8540faf2020-02-04 19:47:20 -080072#include <android/hardware/dumpstate/1.1/IDumpstateDevice.h>
73#include <android/hardware/dumpstate/1.1/types.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080074#include <android/hidl/manager/1.0/IServiceManager.h>
Nandana Duttd2f5f082019-01-18 17:13:52 +000075#include <android/os/IIncidentCompanion.h>
Nikita Ioffea325a572019-05-16 19:49:47 +010076#include <binder/IServiceManager.h>
Nikhil Kumar28ce35e2023-01-10 14:32:44 +000077#include <cutils/multiuser.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080078#include <cutils/native_handle.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070079#include <cutils/properties.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010080#include <cutils/sockets.h>
Kevin Jeon2c02e8e2022-07-07 21:45:17 +000081#include <cutils/trace.h>
Nandana Duttfaafd522019-03-11 09:23:09 +000082#include <debuggerd/client.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080083#include <dumpsys.h>
Nandana Duttfaafd522019-03-11 09:23:09 +000084#include <dumputils/dump_utils.h>
Sahana Raof35ed432019-07-12 10:47:52 +010085#include <hardware_legacy/power.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080086#include <hidl/ServiceManagement.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010087#include <log/log.h>
Tom Cherryf4472f32020-08-05 09:31:17 -070088#include <log/log_read.h>
Felipe Leme75876a22016-10-27 16:31:27 -070089#include <openssl/sha.h>
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070090#include <private/android_filesystem_config.h>
91#include <private/android_logger.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080092#include <serviceutils/PriorityDumper.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070093#include <utils/StrongPointer.h>
Devin Moore8df81bb2022-06-08 22:47:02 +000094#include <vintf/VintfObject.h>
Felipe Lemef0292972016-11-22 13:57:05 -080095#include "DumpstateInternal.h"
Felipe Leme75876a22016-10-27 16:31:27 -070096#include "DumpstateService.h"
Colin Crossf45fa6b2012-03-26 12:38:26 -070097#include "dumpstate.h"
Felipe Leme6e01fa62015-11-11 19:35:14 -080098
Kedar Chitnis9fd8c052021-11-16 09:09:22 +000099namespace dumpstate_hal_hidl_1_0 = android::hardware::dumpstate::V1_0;
100namespace dumpstate_hal_hidl = android::hardware::dumpstate::V1_1;
101namespace dumpstate_hal_aidl = aidl::android::hardware::dumpstate;
102
Vishnu Naire97d6122018-01-18 13:58:56 -0800103using ::std::literals::chrono_literals::operator""ms;
104using ::std::literals::chrono_literals::operator""s;
Rhed Jao5377d792020-07-16 17:37:39 +0800105using ::std::placeholders::_1;
Steven Morelandcb7ef822016-11-29 13:20:37 -0800106
Felipe Leme47e9be22016-12-21 15:37:07 -0800107// TODO: remove once moved to namespace
Vishnu Naire97d6122018-01-18 13:58:56 -0800108using android::defaultServiceManager;
109using android::Dumpsys;
110using android::INVALID_OPERATION;
111using android::IServiceManager;
112using android::OK;
113using android::sp;
114using android::status_t;
115using android::String16;
116using android::String8;
117using android::TIMED_OUT;
118using android::UNKNOWN_ERROR;
119using android::Vector;
Nandana Dutt979388e2018-11-30 16:48:55 +0000120using android::base::StringPrintf;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000121using android::os::IDumpstateListener;
Felipe Leme47e9be22016-12-21 15:37:07 -0800122using android::os::dumpstate::CommandOptions;
123using android::os::dumpstate::DumpFileToFd;
Rhed Jao5377d792020-07-16 17:37:39 +0800124using android::os::dumpstate::DumpPool;
Vishnu Naire97d6122018-01-18 13:58:56 -0800125using android::os::dumpstate::PropertiesHelper;
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800126using android::os::dumpstate::TaskQueue;
Chris Morinbc223142022-02-04 14:17:11 -0800127using android::os::dumpstate::WaitForTask;
Felipe Leme47e9be22016-12-21 15:37:07 -0800128
Abhijeet Kaurcf234e82019-07-01 14:53:55 +0100129// Keep in sync with
130// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
131static const int TRACE_DUMP_TIMEOUT_MS = 10000; // 10 seconds
132
133/* Most simple commands have 10 as timeout, so 5 is a good estimate */
134static const int32_t WEIGHT_FILE = 5;
135
136// TODO: temporary variables and functions used during C++ refactoring
137static Dumpstate& ds = Dumpstate::GetInstance();
138static int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Nandana Dutt8d945c02019-08-14 13:30:07 +0100139 const CommandOptions& options = CommandOptions::DEFAULT,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800140 bool verbose_duration = false, int out_fd = STDOUT_FILENO) {
141 return ds.RunCommand(title, full_command, options, verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +0100142}
143
144// Reasonable value for max stats.
145static const int STATS_MAX_N_RUNS = 1000;
146static const long STATS_MAX_AVERAGE = 100000;
147
148CommandOptions Dumpstate::DEFAULT_DUMPSYS = CommandOptions::WithTimeout(30).Build();
149
Nandana Duttd2f5f082019-01-18 17:13:52 +0000150typedef Dumpstate::ConsentCallback::ConsentResult UserConsentResult;
151
Colin Crossf45fa6b2012-03-26 12:38:26 -0700152/* read before root is shed */
153static char cmdline_buf[16384] = "(unknown)";
Yi Kong19d5c002018-07-20 13:39:55 -0700154static const char *dump_traces_path = nullptr;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000155static const uint64_t USER_CONSENT_TIMEOUT_MS = 30 * 1000;
Hunter Knepshield70610fa2020-01-03 15:27:33 -0800156// Because telephony reports are significantly faster to collect (< 10 seconds vs. > 2 minutes),
157// it's often the case that they time out far too quickly for consent with such a hefty dialog for
158// the user to read. For telephony reports only, we increase the default timeout to 2 minutes to
159// roughly match full reports' durations.
160static const uint64_t TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS = 2 * 60 * 1000;
Colin Crossf45fa6b2012-03-26 12:38:26 -0700161
Felipe Leme1d486fe2016-10-14 18:06:47 -0700162// TODO: variables and functions below should be part of dumpstate object
163
Felipe Leme635ca312016-01-05 14:23:02 -0800164static std::set<std::string> mount_points;
165void add_mountinfo();
Felipe Leme78f2c862015-12-21 09:55:22 -0800166
Todd Poynor2a83daa2013-11-22 15:44:22 -0800167#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
Mark Salyzyn7d0a7622016-06-24 14:06:15 -0700168#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
Wei Wang509bb5d2017-06-09 14:42:12 -0700169#define BLK_DEV_SYS_DIR "/sys/block"
Todd Poynor2a83daa2013-11-22 15:44:22 -0800170
Felipe Lemee82a27d2016-01-05 13:35:44 -0800171#define RECOVERY_DIR "/cache/recovery"
Mark Salyzynd6ab0112016-03-25 12:56:39 -0700172#define RECOVERY_DATA_DIR "/data/misc/recovery"
Tianjie Xu75d53362018-04-11 16:42:28 -0700173#define UPDATE_ENGINE_LOG_DIR "/data/misc/update_engine_log"
Kelvin Zhang6eaa0f92022-09-12 09:29:19 -0700174#define UPDATE_ENGINE_PREF_DIR "/data/misc/update_engine/prefs"
Mark Salyzyn4d42dea2016-04-01 10:03:14 -0700175#define LOGPERSIST_DATA_DIR "/data/misc/logd"
Jerry Changa1df8a92020-01-02 16:03:39 +0800176#define PREREBOOT_DATA_DIR "/data/misc/prereboot"
David Brazdild2991962016-06-03 14:40:44 +0100177#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
178#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
Benedict Wong8f9d8a42019-01-03 16:19:38 -0800179#define XFRM_STAT_PROC_FILE "/proc/net/xfrm_stat"
Steven Moreland9379c462023-12-21 02:04:27 +0000180#define KERNEL_CONFIG "/proc/config.gz"
Erik Kline08165202016-05-30 11:55:44 +0900181#define WLUTIL "/vendor/xbin/wlutil"
Vishnu Nair36b4cdb2017-11-17 10:27:05 -0800182#define WMTRACE_DATA_DIR "/data/misc/wmtrace"
Yifan Hong3945e1b2019-10-29 12:59:23 -0700183#define OTA_METADATA_DIR "/metadata/ota"
Yifan Hong0efa7972020-02-03 16:45:02 -0800184#define SNAPSHOTCTL_LOG_DIR "/data/misc/snapshotctl_log"
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +0900185#define LINKERCONFIG_DIR "/linkerconfig"
Calin Juravlef84d3692020-04-28 15:31:12 -0700186#define PACKAGE_DEX_USE_LIST "/data/system/package-dex-usage.list"
Primiano Tuccifaaaafb2021-01-14 12:26:29 +0000187#define SYSTEM_TRACE_SNAPSHOT "/data/misc/perfetto-traces/bugreport/systrace.pftrace"
Li Li2eedd412021-06-30 15:11:53 -0700188#define CGROUPFS_DIR "/sys/fs/cgroup"
Mårten Kongstad60195a72022-09-20 14:14:20 +0200189#define SDK_EXT_INFO "/apex/com.android.sdkext/bin/derive_sdk"
Jeff Sharkey9df29d52023-02-06 14:26:30 -0700190#define DROPBOX_DIR "/data/system/dropbox"
Mårten Kongstad5ad813f2023-09-28 10:09:18 +0200191#define PRINT_FLAGS "/system/bin/printflags"
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700192
Narayan Kamath8f788292017-05-25 13:20:39 +0100193// TODO(narayan): Since this information has to be kept in sync
194// with tombstoned, we should just put it in a common header.
195//
196// File: system/core/debuggerd/tombstoned/tombstoned.cpp
Narayan Kamathbd863722017-06-01 18:50:12 +0100197static const std::string TOMBSTONE_DIR = "/data/tombstones/";
198static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
199static const std::string ANR_DIR = "/data/anr/";
200static const std::string ANR_FILE_PREFIX = "anr_";
Woody Lin20767a92022-11-29 15:50:24 +0800201static const std::string SHUTDOWN_CHECKPOINTS_DIR = "/data/system/shutdown-checkpoints/";
202static const std::string SHUTDOWN_CHECKPOINTS_FILE_PREFIX = "checkpoints-";
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700203
Felipe Lemee844a9d2016-09-21 15:01:39 -0700204// TODO: temporary variables and functions used during C++ refactoring
Nandana Dutt979388e2018-11-30 16:48:55 +0000205
Nandana Dutt5c390032019-03-12 10:52:56 +0000206#define RETURN_IF_USER_DENIED_CONSENT() \
207 if (ds.IsUserConsentDenied()) { \
208 MYLOGE("Returning early as user denied consent to share bugreport with calling app."); \
209 return Dumpstate::RunStatus::USER_CONSENT_DENIED; \
210 }
211
212// Runs func_ptr, but checks user consent before and after running it. Returns USER_CONSENT_DENIED
213// if consent is found to be denied.
214#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(func_ptr, ...) \
215 RETURN_IF_USER_DENIED_CONSENT(); \
216 func_ptr(__VA_ARGS__); \
217 RETURN_IF_USER_DENIED_CONSENT();
218
Rhed Jao5377d792020-07-16 17:37:39 +0800219// Runs func_ptr, and logs a duration report after it's finished.
220#define RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, ...) \
221 { \
222 DurationReporter duration_reporter_in_macro(log_title); \
223 func_ptr(__VA_ARGS__); \
224 }
225
226// Similar with RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK, an additional duration report
227// is output after a slow function is finished.
228#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(log_title, func_ptr, ...) \
229 RETURN_IF_USER_DENIED_CONSENT(); \
230 RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, __VA_ARGS__); \
231 RETURN_IF_USER_DENIED_CONSENT();
232
Chris Morinbc223142022-02-04 14:17:11 -0800233#define WAIT_TASK_WITH_CONSENT_CHECK(future) \
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800234 RETURN_IF_USER_DENIED_CONSENT(); \
Chris Morinbc223142022-02-04 14:17:11 -0800235 WaitForTask(future); \
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800236 RETURN_IF_USER_DENIED_CONSENT();
237
Sahana Raof35ed432019-07-12 10:47:52 +0100238static const char* WAKE_LOCK_NAME = "dumpstate_wakelock";
239
Rhed Jao5377d792020-07-16 17:37:39 +0800240// Names of parallel tasks, they are used for the DumpPool to identify the dump
241// task and the log title of the duration report.
242static const std::string DUMP_TRACES_TASK = "DUMP TRACES";
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800243static const std::string DUMP_INCIDENT_REPORT_TASK = "INCIDENT REPORT";
Aaron Huanga99452a2022-04-27 18:51:16 +0800244static const std::string DUMP_NETSTATS_PROTO_TASK = "DUMP NETSTATS PROTO";
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800245static const std::string DUMP_HALS_TASK = "DUMP HALS";
246static const std::string DUMP_BOARD_TASK = "dumpstate_board()";
Rhed Jaoe017f982020-07-21 17:58:41 +0800247static const std::string DUMP_CHECKINS_TASK = "DUMP CHECKINS";
Kean Mariotti306633e2022-09-05 16:30:47 +0000248static const std::string POST_PROCESS_UI_TRACES_TASK = "POST-PROCESS UI TRACES";
Rhed Jao5377d792020-07-16 17:37:39 +0800249
Nandana Dutt979388e2018-11-30 16:48:55 +0000250namespace android {
251namespace os {
252namespace {
253
254static int Open(std::string path, int flags, mode_t mode = 0) {
255 int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
256 if (fd == -1) {
257 MYLOGE("open(%s, %s)\n", path.c_str(), strerror(errno));
258 }
259 return fd;
260}
261
mhasank2d75c442020-06-11 15:05:25 -0700262static int OpenForWrite(std::string path) {
263 return Open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
264 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
265}
Nandana Dutt979388e2018-11-30 16:48:55 +0000266
267static int OpenForRead(std::string path) {
268 return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
269}
270
271bool CopyFile(int in_fd, int out_fd) {
272 char buf[4096];
273 ssize_t byte_count;
274 while ((byte_count = TEMP_FAILURE_RETRY(read(in_fd, buf, sizeof(buf)))) > 0) {
275 if (!android::base::WriteFully(out_fd, buf, byte_count)) {
276 return false;
277 }
278 }
279 return (byte_count != -1);
280}
281
282static bool CopyFileToFd(const std::string& input_file, int out_fd) {
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000283 MYLOGD("Going to copy file (%s) to %d\n", input_file.c_str(), out_fd);
Nandana Dutt979388e2018-11-30 16:48:55 +0000284
285 // Obtain a handle to the source file.
286 android::base::unique_fd in_fd(OpenForRead(input_file));
287 if (out_fd != -1 && in_fd.get() != -1) {
288 if (CopyFile(in_fd.get(), out_fd)) {
289 return true;
290 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000291 MYLOGE("Failed to copy file: %s\n", strerror(errno));
Nandana Dutt979388e2018-11-30 16:48:55 +0000292 }
293 return false;
294}
295
Nandana Duttd2f5f082019-01-18 17:13:52 +0000296static bool UnlinkAndLogOnError(const std::string& file) {
Nandana Dutt8ae16e62020-03-27 10:20:22 +0000297 if (file.empty()) {
298 return false;
299 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000300 if (unlink(file.c_str())) {
301 MYLOGE("Failed to unlink file (%s): %s\n", file.c_str(), strerror(errno));
Nandana Duttd2f5f082019-01-18 17:13:52 +0000302 return false;
303 }
304 return true;
305}
Nandana Dutt979388e2018-11-30 16:48:55 +0000306
Nikita Ioffea325a572019-05-16 19:49:47 +0100307int64_t GetModuleMetadataVersion() {
308 auto binder = defaultServiceManager()->getService(android::String16("package_native"));
309 if (binder == nullptr) {
310 MYLOGE("Failed to retrieve package_native service");
311 return 0L;
312 }
313 auto package_service = android::interface_cast<content::pm::IPackageManagerNative>(binder);
314 std::string package_name;
315 auto status = package_service->getModuleMetadataPackageName(&package_name);
316 if (!status.isOk()) {
317 MYLOGE("Failed to retrieve module metadata package name: %s", status.toString8().c_str());
318 return 0L;
319 }
Nandana Duttdb379fa2019-10-09 16:54:41 +0100320 MYLOGD("Module metadata package name: %s\n", package_name.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100321 int64_t version_code;
322 status = package_service->getVersionCodeForPackage(android::String16(package_name.c_str()),
323 &version_code);
324 if (!status.isOk()) {
325 MYLOGE("Failed to retrieve module metadata version: %s", status.toString8().c_str());
326 return 0L;
327 }
328 return version_code;
329}
330
mhasank2d75c442020-06-11 15:05:25 -0700331static bool PathExists(const std::string& path) {
332 struct stat sb;
333 return stat(path.c_str(), &sb) == 0;
334}
335
336static bool CopyFileToFile(const std::string& input_file, const std::string& output_file) {
337 if (input_file == output_file) {
338 MYLOGD("Skipping copying bugreport file since the destination is the same (%s)\n",
339 output_file.c_str());
340 return false;
341 }
342 else if (PathExists(output_file)) {
343 MYLOGD("Cannot overwrite an existing file (%s)\n", output_file.c_str());
344 return false;
345 }
346
347 MYLOGD("Going to copy bugreport file (%s) to %s\n", input_file.c_str(), output_file.c_str());
348 android::base::unique_fd out_fd(OpenForWrite(output_file));
349 return CopyFileToFd(input_file, out_fd.get());
350}
351
Nandana Dutt979388e2018-11-30 16:48:55 +0000352} // namespace
353} // namespace os
354} // namespace android
355
Felipe Leme678727a2016-09-21 17:22:11 -0700356static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
Felipe Lemebda15a02016-11-16 17:48:25 -0800357 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
Rhed Jaoe017f982020-07-21 17:58:41 +0800358 long dumpsysTimeoutMs = 0, int out_fd = STDOUT_FILENO) {
359 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs, out_fd);
360}
361static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
362 int out_fd) {
363 return ds.RunDumpsys(title, dumpsysArgs, Dumpstate::DEFAULT_DUMPSYS, 0, out_fd);
Felipe Leme678727a2016-09-21 17:22:11 -0700364}
365static int DumpFile(const std::string& title, const std::string& path) {
366 return ds.DumpFile(title, path);
367}
Felipe Lemee82a27d2016-01-05 13:35:44 -0800368
Felipe Lemee844a9d2016-09-21 15:01:39 -0700369// Relative directory (inside the zip) for all files copied as-is into the bugreport.
370static const std::string ZIP_ROOT_DIR = "FS";
371
Vishnu Naire97d6122018-01-18 13:58:56 -0800372static const std::string kProtoPath = "proto/";
373static const std::string kProtoExt = ".proto";
Jie Song9fbfad02017-06-20 16:29:42 -0700374static const std::string kDumpstateBoardFiles[] = {
375 "dumpstate_board.txt",
Felipe Leme95d6ca52017-08-01 16:35:56 -0700376 "dumpstate_board.bin"
Jie Song9fbfad02017-06-20 16:29:42 -0700377};
378static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
379
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700380static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Lemed071c682016-10-20 16:48:00 -0700381static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700382
Felipe Lemef0292972016-11-22 13:57:05 -0800383static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
384
Narayan Kamath8f788292017-05-25 13:20:39 +0100385/*
Narayan Kamathbd863722017-06-01 18:50:12 +0100386 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
Rhed Jao01dc0c62020-06-03 17:13:30 +0800387 * The returned vector is sorted by the mtimes of the dumps with descending
Chris Morinc2cba7a2022-02-01 17:06:50 -0800388 * order.
Narayan Kamath8f788292017-05-25 13:20:39 +0100389 */
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700390static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
Chris Morinc2cba7a2022-02-01 17:06:50 -0800391 const std::string& file_prefix) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100392 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100393
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700394 if (dump_dir == nullptr) {
395 MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno));
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700396 return std::vector<DumpData>();
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700397 }
398
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700399 std::vector<DumpData> dump_data;
Narayan Kamathbd863722017-06-01 18:50:12 +0100400 struct dirent* entry = nullptr;
401 while ((entry = readdir(dump_dir.get()))) {
402 if (entry->d_type != DT_REG) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100403 continue;
404 }
405
Narayan Kamathbd863722017-06-01 18:50:12 +0100406 const std::string base_name(entry->d_name);
407 if (base_name.find(file_prefix) != 0) {
408 continue;
409 }
410
411 const std::string abs_path = dir_path + base_name;
412 android::base::unique_fd fd(
413 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
414 if (fd == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700415 MYLOGW("Unable to open dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamathbd863722017-06-01 18:50:12 +0100416 break;
417 }
418
419 struct stat st = {};
420 if (fstat(fd, &st) == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700421 MYLOGW("Unable to stat dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamath8f788292017-05-25 13:20:39 +0100422 continue;
423 }
424
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700425 dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700426 }
Rhed Jao01dc0c62020-06-03 17:13:30 +0800427 if (!dump_data.empty()) {
428 std::sort(dump_data.begin(), dump_data.end(),
429 [](const auto& a, const auto& b) { return a.mtime > b.mtime; });
430 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100431
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700432 return dump_data;
Narayan Kamath8f788292017-05-25 13:20:39 +0100433}
434
Narayan Kamathbd863722017-06-01 18:50:12 +0100435static bool AddDumps(const std::vector<DumpData>::const_iterator start,
436 const std::vector<DumpData>::const_iterator end,
437 const char* type_name, const bool add_to_zip) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100438 bool dumped = false;
Narayan Kamathbd863722017-06-01 18:50:12 +0100439 for (auto it = start; it != end; ++it) {
440 const std::string& name = it->name;
441 const int fd = it->fd;
Narayan Kamath8f788292017-05-25 13:20:39 +0100442 dumped = true;
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100443
444 // Seek to the beginning of the file before dumping any data. A given
445 // DumpData entry might be dumped multiple times in the report.
446 //
447 // For example, the most recent ANR entry is dumped to the body of the
448 // main entry and it also shows up as a separate entry in the bugreport
449 // ZIP file.
450 if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) {
451 MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(),
452 strerror(errno));
453 }
454
Chris Morinc2cba7a2022-02-01 17:06:50 -0800455 if (add_to_zip) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800456 if (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd, /* timeout = */ 0ms) != OK) {
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100457 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100458 }
459 } else {
460 dump_file_from_fd(type_name, name.c_str(), fd);
461 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100462 }
463
464 return dumped;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700465}
466
Felipe Leme635ca312016-01-05 14:23:02 -0800467// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700468void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800469 char path[PATH_MAX];
470
471 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
472 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700473 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800474 char linkname[PATH_MAX];
475 ssize_t r = readlink(path, linkname, PATH_MAX);
476 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800477 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800478 return;
479 }
480 linkname[r] = '\0';
481
482 if (mount_points.find(linkname) == mount_points.end()) {
483 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700484 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700485 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
Felipe Leme635ca312016-01-05 14:23:02 -0800486 mount_points.insert(linkname);
487 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800488 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800489 }
490 }
491}
492
493void add_mountinfo() {
Felipe Leme678727a2016-09-21 17:22:11 -0700494 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800495 mount_points.clear();
Felipe Leme46b85da2016-11-21 17:40:45 -0800496 DurationReporter duration_reporter(title, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700497 for_each_pid(do_mountinfo, nullptr);
498 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800499}
500
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700501static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
502{
503 DIR *d;
504 struct dirent *de;
505 char path[PATH_MAX];
506
507 d = opendir(driverpath);
Yi Kong19d5c002018-07-20 13:39:55 -0700508 if (d == nullptr) {
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700509 return;
510 }
511
512 while ((de = readdir(d))) {
513 if (de->d_type != DT_LNK) {
514 continue;
515 }
516 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700517 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700518 }
519
520 closedir(d);
521}
522
Mark Salyzyn326842f2015-04-30 09:49:41 -0700523static bool skip_not_stat(const char *path) {
524 static const char stat[] = "/stat";
525 size_t len = strlen(path);
526 if (path[len - 1] == '/') { /* Directory? */
527 return false;
528 }
529 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
530}
531
Jeff Sharkey9df29d52023-02-06 14:26:30 -0700532static bool skip_wtf_strictmode(const char *path) {
533 if (strstr(path, "_wtf")) {
534 return true;
535 } else if (strstr(path, "_strictmode")) {
536 return true;
537 }
538 return false;
539}
540
Felipe Leme4c2d6632016-09-28 14:32:00 -0700541static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800542 return false;
543}
544
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700545unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700546
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800547//
548// stat offsets
549// Name units description
550// ---- ----- -----------
551// read I/Os requests number of read I/Os processed
552#define __STAT_READ_IOS 0
553// read merges requests number of read I/Os merged with in-queue I/O
554#define __STAT_READ_MERGES 1
555// read sectors sectors number of sectors read
556#define __STAT_READ_SECTORS 2
557// read ticks milliseconds total wait time for read requests
558#define __STAT_READ_TICKS 3
559// write I/Os requests number of write I/Os processed
560#define __STAT_WRITE_IOS 4
561// write merges requests number of write I/Os merged with in-queue I/O
562#define __STAT_WRITE_MERGES 5
563// write sectors sectors number of sectors written
564#define __STAT_WRITE_SECTORS 6
565// write ticks milliseconds total wait time for write requests
566#define __STAT_WRITE_TICKS 7
567// in_flight requests number of I/Os currently in flight
568#define __STAT_IN_FLIGHT 8
569// io_ticks milliseconds total time this block device has been active
570#define __STAT_IO_TICKS 9
571// time_in_queue milliseconds total wait time for all requests
572#define __STAT_IN_QUEUE 10
573#define __STAT_NUMBER_FIELD 11
574//
575// read I/Os, write I/Os
576// =====================
577//
578// These values increment when an I/O request completes.
579//
580// read merges, write merges
581// =========================
582//
583// These values increment when an I/O request is merged with an
584// already-queued I/O request.
585//
586// read sectors, write sectors
587// ===========================
588//
589// These values count the number of sectors read from or written to this
590// block device. The "sectors" in question are the standard UNIX 512-byte
591// sectors, not any device- or filesystem-specific block size. The
592// counters are incremented when the I/O completes.
593#define SECTOR_SIZE 512
594//
595// read ticks, write ticks
596// =======================
597//
598// These values count the number of milliseconds that I/O requests have
599// waited on this block device. If there are multiple I/O requests waiting,
600// these values will increase at a rate greater than 1000/second; for
601// example, if 60 read requests wait for an average of 30 ms, the read_ticks
602// field will increase by 60*30 = 1800.
603//
604// in_flight
605// =========
606//
607// This value counts the number of I/O requests that have been issued to
608// the device driver but have not yet completed. It does not include I/O
609// requests that are in the queue but not yet issued to the device driver.
610//
611// io_ticks
612// ========
613//
614// This value counts the number of milliseconds during which the device has
615// had I/O requests queued.
616//
617// time_in_queue
618// =============
619//
620// This value counts the number of milliseconds that I/O requests have waited
621// on this block device. If there are multiple I/O requests waiting, this
622// value will increase as the product of the number of milliseconds times the
623// number of requests waiting (see "read ticks" above for an example).
624#define S_TO_MS 1000
625//
626
Mark Salyzyn326842f2015-04-30 09:49:41 -0700627static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800628 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700629 bool z;
Yi Kong19d5c002018-07-20 13:39:55 -0700630 char *cp, *buffer = nullptr;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700631 size_t i = 0;
Josh Gao7c4258c2018-06-25 13:40:08 -0700632 FILE *fp = fdopen(dup(fd), "rb");
Mark Salyzyn326842f2015-04-30 09:49:41 -0700633 getline(&buffer, &i, fp);
634 fclose(fp);
635 if (!buffer) {
636 return -errno;
637 }
638 i = strlen(buffer);
639 while ((i > 0) && (buffer[i - 1] == '\n')) {
640 buffer[--i] = '\0';
641 }
642 if (!*buffer) {
643 free(buffer);
644 return 0;
645 }
646 z = true;
647 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800648 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700649 if (fields[i] != 0) {
650 z = false;
651 }
652 }
653 if (z) { /* never accessed */
654 free(buffer);
655 return 0;
656 }
657
Wei Wang509bb5d2017-06-09 14:42:12 -0700658 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
659 path += sizeof(BLK_DEV_SYS_DIR) - 1;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700660 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700661
662 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
663 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
664 "W-wait", "in-fli", "activ", "T-wait", path, buffer);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700665 free(buffer);
666
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800667 if (fields[__STAT_IO_TICKS]) {
668 unsigned long read_perf = 0;
669 unsigned long read_ios = 0;
670 if (fields[__STAT_READ_TICKS]) {
671 unsigned long long divisor = fields[__STAT_READ_TICKS]
672 * fields[__STAT_IO_TICKS];
673 read_perf = ((unsigned long long)SECTOR_SIZE
674 * fields[__STAT_READ_SECTORS]
675 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
676 / divisor;
677 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
678 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
679 / divisor;
680 }
681
682 unsigned long write_perf = 0;
683 unsigned long write_ios = 0;
684 if (fields[__STAT_WRITE_TICKS]) {
685 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
686 * fields[__STAT_IO_TICKS];
687 write_perf = ((unsigned long long)SECTOR_SIZE
688 * fields[__STAT_WRITE_SECTORS]
689 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
690 / divisor;
691 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
692 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
693 / divisor;
694 }
695
696 unsigned queue = (fields[__STAT_IN_QUEUE]
697 + (fields[__STAT_IO_TICKS] >> 1))
698 / fields[__STAT_IO_TICKS];
699
700 if (!write_perf && !write_ios) {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700701 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 -0800702 } else {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700703 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 -0800704 read_ios, write_perf, write_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800705 }
706
707 /* bugreport timeout factor adjustment */
708 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
709 worst_write_perf = write_perf;
710 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700711 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700712 return 0;
713}
714
Yao Chenbe3bbc12018-01-17 16:31:10 -0800715static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
716
Tom Cherryf4472f32020-08-05 09:31:17 -0700717// Returns the actual readable size of the given buffer or -1 on error.
718static long logcat_buffer_readable_size(const std::string& buffer) {
719 std::unique_ptr<logger_list, decltype(&android_logger_list_free)> logger_list{
720 android_logger_list_alloc(0, 0, 0), &android_logger_list_free};
721 auto logger = android_logger_open(logger_list.get(), android_name_to_log_id(buffer.c_str()));
722
723 return android_logger_get_log_readable_size(logger);
724}
725
726// Returns timeout in ms to read a list of buffers.
Yao Chenbe3bbc12018-01-17 16:31:10 -0800727static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
728 unsigned long timeout_ms = 0;
729 for (const auto& buffer : buffers) {
Tom Cherryf4472f32020-08-05 09:31:17 -0700730 long readable_size = logcat_buffer_readable_size(buffer);
731 if (readable_size > 0) {
732 // Engineering margin is ten-fold our guess.
733 timeout_ms += 10 * (readable_size + worst_write_perf) / worst_write_perf;
734 }
Yao Chenbe3bbc12018-01-17 16:31:10 -0800735 }
736 return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700737}
738
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800739// Opens a socket and returns its file descriptor.
740static int open_socket(const char* service);
741
Nandana Duttd2f5f082019-01-18 17:13:52 +0000742Dumpstate::ConsentCallback::ConsentCallback() : result_(UNAVAILABLE), start_time_(Nanotime()) {
743}
744
745android::binder::Status Dumpstate::ConsentCallback::onReportApproved() {
746 std::lock_guard<std::mutex> lock(lock_);
747 result_ = APPROVED;
748 MYLOGD("User approved consent to share bugreport\n");
Paul Chang0d2aad72020-02-13 20:04:03 +0800749
750 // Maybe copy screenshot so calling app can display the screenshot to the user as soon as
751 // consent is granted.
752 if (ds.options_->is_screenshot_copied) {
753 return android::binder::Status::ok();
754 }
755
756 if (!ds.options_->do_screenshot || ds.options_->screenshot_fd.get() == -1 ||
757 !ds.do_early_screenshot_) {
758 return android::binder::Status::ok();
759 }
760
761 bool copy_succeeded = android::os::CopyFileToFd(ds.screenshot_path_,
762 ds.options_->screenshot_fd.get());
763 ds.options_->is_screenshot_copied = copy_succeeded;
764 if (copy_succeeded) {
765 android::os::UnlinkAndLogOnError(ds.screenshot_path_);
766 }
Nandana Duttd2f5f082019-01-18 17:13:52 +0000767 return android::binder::Status::ok();
768}
769
770android::binder::Status Dumpstate::ConsentCallback::onReportDenied() {
771 std::lock_guard<std::mutex> lock(lock_);
772 result_ = DENIED;
773 MYLOGW("User denied consent to share bugreport\n");
774 return android::binder::Status::ok();
775}
776
777UserConsentResult Dumpstate::ConsentCallback::getResult() {
778 std::lock_guard<std::mutex> lock(lock_);
779 return result_;
780}
781
782uint64_t Dumpstate::ConsentCallback::getElapsedTimeMs() const {
Hunter Knepshieldf0a39052020-01-03 14:53:04 -0800783 return (Nanotime() - start_time_) / NANOS_PER_MILLI;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000784}
785
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700786void Dumpstate::PrintHeader() const {
Mårten Kongstad60195a72022-09-20 14:14:20 +0200787 std::string build, fingerprint, radio, bootloader, network, sdkversion;
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700788 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700789
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700790 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
791 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700792 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
793 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
794 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
Mårten Kongstad60195a72022-09-20 14:14:20 +0200795 sdkversion = android::base::GetProperty("ro.build.version.sdk", "(unknown)");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700796 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
Colin Crossf45fa6b2012-03-26 12:38:26 -0700797
Felipe Lemed8b94e52016-12-08 10:21:44 -0800798 printf("========================================================\n");
799 printf("== dumpstate: %s\n", date);
800 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700801
Felipe Lemed8b94e52016-12-08 10:21:44 -0800802 printf("\n");
803 printf("Build: %s\n", build.c_str());
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700804 // NOTE: fingerprint entry format is important for other tools.
Felipe Lemed8b94e52016-12-08 10:21:44 -0800805 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
806 printf("Bootloader: %s\n", bootloader.c_str());
807 printf("Radio: %s\n", radio.c_str());
808 printf("Network: %s\n", network.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100809 int64_t module_metadata_version = android::os::GetModuleMetadataVersion();
810 if (module_metadata_version != 0) {
811 printf("Module Metadata version: %" PRId64 "\n", module_metadata_version);
812 }
Mårten Kongstad60195a72022-09-20 14:14:20 +0200813 printf("Android SDK version: %s\n", sdkversion.c_str());
814 printf("SDK extensions: ");
815 RunCommandToFd(STDOUT_FILENO, "", {SDK_EXT_INFO, "--header"},
816 CommandOptions::WithTimeout(1).Always().DropRoot().Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700817
Felipe Lemed8b94e52016-12-08 10:21:44 -0800818 printf("Kernel: ");
Felipe Lemef0292972016-11-22 13:57:05 -0800819 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
Felipe Lemed8b94e52016-12-08 10:21:44 -0800820 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
Devin Moore09fde8d2023-03-21 16:28:22 +0000821 printf("Bootconfig: ");
822 DumpFileToFd(STDOUT_FILENO, "", "/proc/bootconfig");
Felipe Leme7709f8a2017-12-05 09:30:09 -0800823 printf("Uptime: ");
824 RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"},
825 CommandOptions::WithTimeout(1).Always().Build());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800826 printf("Bugreport format version: %s\n", version_.c_str());
Kevin Jeonfa64e642023-07-27 11:36:41 -0400827 printf(
828 "Dumpstate info: id=%d pid=%d dry_run=%d parallel_run=%d strict_run=%d args=%s "
829 "bugreport_mode=%s\n",
830 id_, pid_, PropertiesHelper::IsDryRun(), PropertiesHelper::IsParallelRun(),
831 PropertiesHelper::IsStrictRun(), options_->args.c_str(),
832 options_->bugreport_mode_string.c_str());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800833 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800834}
835
Felipe Leme24b66ee2016-06-16 10:55:26 -0700836// List of file extensions that can cause a zip file attachment to be rejected by some email
837// service providers.
838static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
839 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
840 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
841 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
842};
843
Vishnu Naire97d6122018-01-18 13:58:56 -0800844status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd,
845 std::chrono::milliseconds timeout = 0ms) {
Felipe Leme24b66ee2016-06-16 10:55:26 -0700846 std::string valid_name = entry_name;
847
848 // Rename extension if necessary.
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -0700849 size_t idx = entry_name.rfind('.');
Felipe Leme24b66ee2016-06-16 10:55:26 -0700850 if (idx != std::string::npos) {
851 std::string extension = entry_name.substr(idx);
852 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
853 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
854 valid_name = entry_name + ".renamed";
855 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
856 }
857 }
858
Felipe Leme6fe9db62016-02-12 09:04:16 -0800859 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
860 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Kevin Jeon9bbe0ac2022-05-05 22:05:43 +0000861 size_t flags = ZipWriter::kCompress | ZipWriter::kDefaultCompression;
862 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), flags,
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700863 get_mtime(fd, ds.now_));
Felipe Leme1d486fe2016-10-14 18:06:47 -0700864 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700865 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700866 ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800867 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800868 }
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000869 bool finished_entry = false;
870 auto finish_entry = [this, &finished_entry] {
871 if (!finished_entry) {
872 // This should only be called when we're going to return an earlier error,
873 // which would've been logged. This may imply the file is already corrupt
874 // and any further logging from FinishEntry is more likely to mislead than
875 // not.
876 this->zip_writer_->FinishEntry();
877 }
878 };
879 auto scope_guard = android::base::make_scope_guard(finish_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -0800880 auto start = std::chrono::steady_clock::now();
881 auto end = start + timeout;
882 struct pollfd pfd = {fd, POLLIN};
Felipe Lemee82a27d2016-01-05 13:35:44 -0800883
Felipe Leme770410d2016-01-26 17:07:14 -0800884 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800885 while (1) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800886 if (timeout.count() > 0) {
887 // lambda to recalculate the timeout.
888 auto time_left_ms = [end]() {
889 auto now = std::chrono::steady_clock::now();
890 auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
891 return std::max(diff.count(), 0LL);
892 };
893
894 int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
895 if (rc < 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000896 MYLOGE("Error in poll while adding from fd to zip entry %s:%s\n",
897 entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800898 return -errno;
899 } else if (rc == 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000900 MYLOGE("Timed out adding from fd to zip entry %s:%s Timeout:%lldms\n",
Vishnu Naire97d6122018-01-18 13:58:56 -0800901 entry_name.c_str(), strerror(errno), timeout.count());
902 return TIMED_OUT;
903 }
904 }
905
Zach Riggle22200402016-08-18 01:01:24 -0400906 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800907 if (bytes_read == 0) {
908 break;
909 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800910 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800911 return -errno;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800912 }
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700913 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800914 if (err) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700915 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800916 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800917 }
918 }
919
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700920 err = zip_writer_->FinishEntry();
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000921 finished_entry = true;
Felipe Leme1d486fe2016-10-14 18:06:47 -0700922 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700923 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800924 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800925 }
926
Vishnu Naire97d6122018-01-18 13:58:56 -0800927 return OK;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800928}
929
Felipe Leme1d486fe2016-10-14 18:06:47 -0700930bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
931 android::base::unique_fd fd(
932 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700933 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800934 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800935 return false;
936 }
937
Vishnu Naire97d6122018-01-18 13:58:56 -0800938 return (AddZipEntryFromFd(entry_name, fd.get()) == OK);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800939}
940
941/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700942static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800943 return (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) == OK) ? 0 : 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800944}
945
Felipe Leme1d486fe2016-10-14 18:06:47 -0700946void Dumpstate::AddDir(const std::string& dir, bool recursive) {
Felipe Leme678727a2016-09-21 17:22:11 -0700947 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
Felipe Leme46b85da2016-11-21 17:40:45 -0800948 DurationReporter duration_reporter(dir, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700949 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800950}
951
Felipe Leme1d486fe2016-10-14 18:06:47 -0700952bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800953 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Kevin Jeon9bbe0ac2022-05-05 22:05:43 +0000954 size_t flags = ZipWriter::kCompress | ZipWriter::kDefaultCompression;
955 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), flags, ds.now_);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700956 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700957 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700958 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800959 return false;
960 }
961
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700962 err = zip_writer_->WriteBytes(content.c_str(), content.length());
Felipe Leme1d486fe2016-10-14 18:06:47 -0700963 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700964 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700965 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800966 return false;
967 }
968
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700969 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700970 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700971 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800972 return false;
973 }
974
975 return true;
976}
977
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800978static void DoKmsg() {
979 struct stat st;
980 if (!stat(PSTORE_LAST_KMSG, &st)) {
981 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
982 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
983 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
984 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
985 } else {
986 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
987 DumpFile("LAST KMSG", "/proc/last_kmsg");
988 }
989}
990
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800991static void DoKernelLogcat() {
Yao Chenbe3bbc12018-01-17 16:31:10 -0800992 unsigned long timeout_ms = logcat_timeout({"kernel"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800993 RunCommand(
994 "KERNEL LOG",
995 {"logcat", "-b", "kernel", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
996 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
997}
998
Nandana Duttdb379fa2019-10-09 16:54:41 +0100999static void DoSystemLogcat(time_t since) {
1000 char since_str[80];
1001 strftime(since_str, sizeof(since_str), "%Y-%m-%d %H:%M:%S.000", localtime(&since));
1002
1003 unsigned long timeout_ms = logcat_timeout({"main", "system", "crash"});
1004 RunCommand("SYSTEM LOG",
1005 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v", "-T",
1006 since_str},
1007 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1008}
1009
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001010static void DoRadioLogcat() {
1011 unsigned long timeout_ms = logcat_timeout({"radio"});
1012 RunCommand(
1013 "RADIO LOG",
1014 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1015 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
1016}
1017
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001018static void DoLogcat() {
Vishnu Nair6921f802017-11-22 09:17:23 -08001019 unsigned long timeout_ms;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001020 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
1021 // calculate timeout
Yao Chenbe3bbc12018-01-17 16:31:10 -08001022 timeout_ms = logcat_timeout({"main", "system", "crash"});
Tony Makae737652017-03-30 17:47:09 +01001023 RunCommand("SYSTEM LOG",
Vishnu Nair6921f802017-11-22 09:17:23 -08001024 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1025 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -08001026 timeout_ms = logcat_timeout({"events"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001027 RunCommand(
1028 "EVENT LOG",
1029 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001030 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Yao Chenbe3bbc12018-01-17 16:31:10 -08001031 timeout_ms = logcat_timeout({"stats"});
1032 RunCommand(
1033 "STATS LOG",
1034 {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001035 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001036 DoRadioLogcat();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001037
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001038 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001039 RunCommand("LAST LOGCAT", {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable",
1040 "-v", "uid", "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001041}
1042
Mike Ma5c267872019-08-21 11:31:34 -07001043static void DumpIncidentReport() {
Mike Ma5c267872019-08-21 11:31:34 -07001044 const std::string path = ds.bugreport_internal_dir_ + "/tmp_incident_report";
1045 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1046 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1047 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1048 if (fd < 0) {
1049 MYLOGE("Could not open %s to dump incident report.\n", path.c_str());
1050 return;
1051 }
Kevin Jeonfa64e642023-07-27 11:36:41 -04001052 RunCommandToFd(fd, "", {"incident", "-u"},
1053 CommandOptions::WithTimeout(PropertiesHelper::IsStrictRun() ? 20 : 120).Build());
Mike Ma5c267872019-08-21 11:31:34 -07001054 bool empty = 0 == lseek(fd, 0, SEEK_END);
1055 if (!empty) {
1056 // Use a different name from "incident.proto"
1057 // /proto/incident.proto is reserved for incident service dump
1058 // i.e. metadata for debugging.
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001059 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "incident_report" + kProtoExt,
1060 path);
1061 } else {
1062 unlink(path.c_str());
Mike Ma5c267872019-08-21 11:31:34 -07001063 }
Mike Ma5c267872019-08-21 11:31:34 -07001064}
1065
Aaron Huanga99452a2022-04-27 18:51:16 +08001066static void DumpNetstatsProto() {
1067 const std::string path = ds.bugreport_internal_dir_ + "/tmp_netstats_proto";
1068 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1069 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1070 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1071 if (fd < 0) {
1072 MYLOGE("Could not open %s to dump netstats proto.\n", path.c_str());
1073 return;
1074 }
1075 RunCommandToFd(fd, "", {"dumpsys", "netstats", "--proto"},
Kevin Jeon2fb3dd62022-09-28 18:48:55 +00001076 CommandOptions::WithTimeout(5).Build());
Aaron Huanga99452a2022-04-27 18:51:16 +08001077 bool empty = 0 == lseek(fd, 0, SEEK_END);
1078 if (!empty) {
1079 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "netstats" + kProtoExt,
1080 path);
1081 } else {
1082 unlink(path.c_str());
1083 }
1084}
1085
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001086static void MaybeAddSystemTraceToZip() {
1087 // This function copies into the .zip the system trace that was snapshotted
1088 // by the early call to MaybeSnapshotSystemTrace(), if any background
1089 // tracing was happening.
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001090 if (!ds.has_system_trace_) {
1091 // No background trace was happening at the time dumpstate was invoked.
1092 return;
1093 }
1094 ds.AddZipEntry(
1095 ZIP_ROOT_DIR + SYSTEM_TRACE_SNAPSHOT,
1096 SYSTEM_TRACE_SNAPSHOT);
1097 android::os::UnlinkAndLogOnError(SYSTEM_TRACE_SNAPSHOT);
1098}
1099
Sunny Goyal35949782019-11-19 15:54:36 -08001100static void DumpVisibleWindowViews() {
Sunny Goyal35949782019-11-19 15:54:36 -08001101 DurationReporter duration_reporter("VISIBLE WINDOW VIEWS");
1102 const std::string path = ds.bugreport_internal_dir_ + "/tmp_visible_window_views";
1103 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1104 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1105 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1106 if (fd < 0) {
1107 MYLOGE("Could not open %s to dump visible views.\n", path.c_str());
1108 return;
1109 }
1110 RunCommandToFd(fd, "", {"cmd", "window", "dump-visible-window-views"},
Kevin Jeon774abde2022-09-28 18:20:43 +00001111 CommandOptions::WithTimeout(10).Build());
Sunny Goyal35949782019-11-19 15:54:36 -08001112 bool empty = 0 == lseek(fd, 0, SEEK_END);
1113 if (!empty) {
1114 ds.AddZipEntry("visible_windows.zip", path);
1115 } else {
1116 MYLOGW("Failed to dump visible windows\n");
1117 }
1118 unlink(path.c_str());
1119}
1120
Jayachandran Ca94c7172017-06-10 15:08:12 -07001121static void DumpIpTablesAsRoot() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001122 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
1123 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +09001124 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001125 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +09001126 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
1127 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
1128 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
1129 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001130}
1131
Woody Lin20767a92022-11-29 15:50:24 +08001132static void DumpShutdownCheckpoints() {
1133 const bool shutdown_checkpoints_dumped = AddDumps(
1134 ds.shutdown_checkpoints_.begin(), ds.shutdown_checkpoints_.end(),
1135 "SHUTDOWN CHECKPOINTS", false /* add_to_zip */);
1136 if (!shutdown_checkpoints_dumped) {
1137 printf("*** NO SHUTDOWN CHECKPOINTS to dump in %s\n\n",
1138 SHUTDOWN_CHECKPOINTS_DIR.c_str());
1139 }
1140}
1141
David Andersond9ba4752018-12-11 18:26:59 -08001142static void DumpDynamicPartitionInfo() {
1143 if (!::android::base::GetBoolProperty("ro.boot.dynamic_partitions", false)) {
1144 return;
1145 }
1146
1147 RunCommand("LPDUMP", {"lpdump", "--all"});
David Anderson6650ade2019-10-02 15:18:59 -07001148 RunCommand("DEVICE-MAPPER", {"gsid", "dump-device-mapper"});
David Andersond9ba4752018-12-11 18:26:59 -08001149}
1150
Chris Morin5a50d482022-02-01 17:41:18 -08001151static void AddAnrTraceDir(const std::string& anr_traces_dir) {
Narayan Kamath8f788292017-05-25 13:20:39 +01001152 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
1153 anr_traces_dir.c_str());
1154
1155 // If we're here, dump_traces_path will always be a temporary file
1156 // (created with mkostemp or similar) that contains dumps taken earlier
1157 // on in the process.
1158 if (dump_traces_path != nullptr) {
Chris Morin5a50d482022-02-01 17:41:18 -08001159 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
1160 dump_traces_path);
1161 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
Narayan Kamath8f788292017-05-25 13:20:39 +01001162
1163 const int ret = unlink(dump_traces_path);
1164 if (ret == -1) {
1165 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
1166 strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -07001167 }
1168 }
1169
Narayan Kamathbd863722017-06-01 18:50:12 +01001170 // Add a specific message for the first ANR Dump.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001171 if (ds.anr_data_.size() > 0) {
Chris Morin5a50d482022-02-01 17:41:18 -08001172 // The "last" ANR will always be present in the body of the main entry.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001173 AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1,
Chris Morin5a50d482022-02-01 17:41:18 -08001174 "VM TRACES AT LAST ANR", false /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001175
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001176 // Historical ANRs are always included as separate entries in the bugreport zip file.
Chris Morin5a50d482022-02-01 17:41:18 -08001177 AddDumps(ds.anr_data_.begin(), ds.anr_data_.end(),
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001178 "HISTORICAL ANR", true /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001179 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +01001180 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
1181 }
1182}
1183
1184static void AddAnrTraceFiles() {
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001185 std::string anr_traces_dir = "/data/anr";
Narayan Kamath8f788292017-05-25 13:20:39 +01001186
Chris Morin5a50d482022-02-01 17:41:18 -08001187 AddAnrTraceDir(anr_traces_dir);
Narayan Kamath8f788292017-05-25 13:20:39 +01001188
Makoto Onuki83ec63f2019-01-31 17:08:59 -08001189 RunCommand("ANR FILES", {"ls", "-lt", ANR_DIR});
1190
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001191 // Slow traces for slow operations.
Felipe Lemee184f662016-10-27 10:04:47 -07001192 struct stat st;
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001193 int i = 0;
1194 while (true) {
1195 const std::string slow_trace_path =
1196 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
1197 if (stat(slow_trace_path.c_str(), &st)) {
1198 // No traces file at this index, done with the files.
1199 break;
Felipe Lemee184f662016-10-27 10:04:47 -07001200 }
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001201 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
1202 i++;
Felipe Lemee184f662016-10-27 10:04:47 -07001203 }
1204}
1205
Wei Wang509bb5d2017-06-09 14:42:12 -07001206static void DumpBlockStatFiles() {
1207 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -07001208
Wei Wang1dc1ef52017-06-12 11:28:37 -07001209 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
1210
1211 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001212 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1213 return;
1214 }
1215
1216 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -07001217 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001218 if ((d->d_name[0] == '.')
1219 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1220 || (d->d_name[1] == '\0'))) {
1221 continue;
1222 }
1223 const std::string new_path =
1224 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1225 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1226 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1227 printf("\n");
1228 }
Wei Wang1dc1ef52017-06-12 11:28:37 -07001229 return;
Wei Wang509bb5d2017-06-09 14:42:12 -07001230}
Jayachandran Ca94c7172017-06-10 15:08:12 -07001231
1232static void DumpPacketStats() {
1233 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
Jayachandran Ca94c7172017-06-10 15:08:12 -07001234}
1235
1236static void DumpIpAddrAndRules() {
1237 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
Ray Chencbf278a2023-11-20 07:49:45 +00001238 RunCommand("NETWORK INTERFACES", {"ip", "-s", "link"});
Jayachandran Ca94c7172017-06-10 15:08:12 -07001239 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1240 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1241 RunCommand("IP RULES", {"ip", "rule", "show"});
1242 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1243}
1244
Nandana Dutt5c390032019-03-12 10:52:56 +00001245static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, int priority,
1246 std::chrono::milliseconds timeout,
1247 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001248 auto start = std::chrono::steady_clock::now();
Vishnu Naire97d6122018-01-18 13:58:56 -08001249 sp<android::IServiceManager> sm = defaultServiceManager();
1250 Dumpsys dumpsys(sm.get());
Vishnu Naire97d6122018-01-18 13:58:56 -08001251 Vector<String16> args;
1252 Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
Vishnu Naire97d6122018-01-18 13:58:56 -08001253 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1254 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001255 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001256 std::string path(title);
1257 path.append(" - ").append(String8(service).c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -08001258 size_t bytes_written = 0;
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001259 if (PropertiesHelper::IsDryRun()) {
1260 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1261 dumpsys.writeDumpFooter(STDOUT_FILENO, service, std::chrono::milliseconds(1));
1262 } else {
Devin Mooref492c1a2023-03-15 19:19:03 +00001263 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP | Dumpsys::TYPE_PID |
1264 Dumpsys::TYPE_CLIENTS | Dumpsys::TYPE_THREAD,
Devin Mooreae68df22023-02-24 20:59:51 +00001265 service, args);
1266 if (status == OK) {
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001267 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1268 std::chrono::duration<double> elapsed_seconds;
1269 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH &&
1270 service == String16("meminfo")) {
1271 // Use a longer timeout for meminfo, since 30s is not always enough.
1272 status = dumpsys.writeDump(STDOUT_FILENO, service, 60s,
1273 /* as_proto = */ false, elapsed_seconds,
1274 bytes_written);
1275 } else {
1276 status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
1277 /* as_proto = */ false, elapsed_seconds,
1278 bytes_written);
1279 }
1280 dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
1281 bool dump_complete = (status == OK);
1282 dumpsys.stopDumpThread(dump_complete);
Devin Moorecdfa4602023-03-16 20:49:39 +00001283 } else {
1284 MYLOGE("Failed to start dump thread for service: %s, status: %d",
1285 String8(service).c_str(), status);
Gavin Corkeryfac7e2b2021-07-08 22:39:02 +01001286 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001287 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001288
1289 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1290 std::chrono::steady_clock::now() - start);
1291 if (elapsed_duration > timeout) {
1292 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1293 elapsed_duration.count());
1294 break;
1295 }
1296 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001297 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001298}
1299
Vishnu Nair64afc022018-02-01 15:29:34 -08001300static void RunDumpsysText(const std::string& title, int priority,
1301 std::chrono::milliseconds timeout,
1302 std::chrono::milliseconds service_timeout) {
1303 DurationReporter duration_reporter(title);
1304 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1305 fsync(STDOUT_FILENO);
1306 RunDumpsysTextByPriority(title, priority, timeout, service_timeout);
1307}
1308
1309/* Dump all services registered with Normal or Default priority. */
Nandana Dutt5c390032019-03-12 10:52:56 +00001310static Dumpstate::RunStatus RunDumpsysTextNormalPriority(const std::string& title,
1311 std::chrono::milliseconds timeout,
1312 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001313 DurationReporter duration_reporter(title);
1314 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1315 fsync(STDOUT_FILENO);
1316 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout,
1317 service_timeout);
Nandana Dutt5c390032019-03-12 10:52:56 +00001318
1319 RETURN_IF_USER_DENIED_CONSENT();
1320
1321 return RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1322 service_timeout);
Vishnu Nair64afc022018-02-01 15:29:34 -08001323}
1324
Nandana Dutt5c390032019-03-12 10:52:56 +00001325static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priority,
1326 std::chrono::milliseconds timeout,
1327 std::chrono::milliseconds service_timeout) {
Vishnu Naire97d6122018-01-18 13:58:56 -08001328 sp<android::IServiceManager> sm = defaultServiceManager();
1329 Dumpsys dumpsys(sm.get());
1330 Vector<String16> args;
1331 Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
1332 DurationReporter duration_reporter(title);
1333
1334 auto start = std::chrono::steady_clock::now();
1335 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
1336 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001337 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001338 std::string path(kProtoPath);
1339 path.append(String8(service).c_str());
1340 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
1341 path.append("_CRITICAL");
1342 } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
1343 path.append("_HIGH");
1344 }
1345 path.append(kProtoExt);
Steven Morelandcbd69fc2021-07-20 20:45:43 +00001346 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP, service, args);
Vishnu Naire97d6122018-01-18 13:58:56 -08001347 if (status == OK) {
1348 status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
1349 bool dumpTerminated = (status == OK);
1350 dumpsys.stopDumpThread(dumpTerminated);
1351 }
1352 ZipWriter::FileEntry file_entry;
1353 ds.zip_writer_->GetLastEntry(&file_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -08001354
1355 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1356 std::chrono::steady_clock::now() - start);
1357 if (elapsed_duration > timeout) {
1358 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1359 elapsed_duration.count());
1360 break;
1361 }
1362 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001363 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001364}
1365
Nandana Dutta7db6342018-11-21 14:53:34 +00001366// Runs dumpsys on services that must dump first and will take less than 100ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001367static Dumpstate::RunStatus RunDumpsysCritical() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001368 RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1369 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Nandana Dutt5c390032019-03-12 10:52:56 +00001370
1371 RETURN_IF_USER_DENIED_CONSENT();
1372
1373 return RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1374 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Vishnu Nair780b1282017-10-10 13:57:24 -07001375}
1376
1377// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001378static Dumpstate::RunStatus RunDumpsysHigh() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001379 // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
1380 // high priority. Reduce timeout once they are able to dump in a shorter time or
1381 // moved to a parallel task.
1382 RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1383 /* timeout= */ 90s, /* service_timeout= */ 30s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001384
1385 RETURN_IF_USER_DENIED_CONSENT();
1386
1387 return RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1388 /* timeout= */ 5s, /* service_timeout= */ 1s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001389}
1390
1391// Runs dumpsys on services that must dump but can take up to 10s to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001392static Dumpstate::RunStatus RunDumpsysNormal() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001393 RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001394
1395 RETURN_IF_USER_DENIED_CONSENT();
1396
1397 return RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1398 /* timeout= */ 90s, /* service_timeout= */ 10s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001399}
1400
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001401/*
1402 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1403 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1404 * if it's not running in the parallel task.
1405 */
1406static void DumpHals(int out_fd = STDOUT_FILENO) {
Yifan Hong30528a22020-08-07 18:24:06 -07001407 RunCommand("HARDWARE HALS", {"lshal", "--all", "--types=all"},
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001408 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build(),
1409 false, out_fd);
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001410
Steven Moreland44cd9482018-01-04 16:24:13 -08001411 using android::hidl::manager::V1_0::IServiceManager;
1412 using android::hardware::defaultServiceManager;
1413
1414 sp<IServiceManager> sm = defaultServiceManager();
1415 if (sm == nullptr) {
1416 MYLOGE("Could not retrieve hwservicemanager to dump hals.\n");
1417 return;
1418 }
1419
1420 auto ret = sm->list([&](const auto& interfaces) {
1421 for (const std::string& interface : interfaces) {
1422 std::string cleanName = interface;
Steven Morelandc6b1fc22023-07-26 23:53:58 +00001423 std::replace_if(
1424 cleanName.begin(), cleanName.end(),
1425 [](char c) {
1426 return !isalnum(c) && std::string("@-_.").find(c) == std::string::npos;
1427 },
1428 '_');
Nandana Dutt979388e2018-11-30 16:48:55 +00001429 const std::string path = ds.bugreport_internal_dir_ + "/lshal_debug_" + cleanName;
Steven Moreland44cd9482018-01-04 16:24:13 -08001430
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001431 bool empty = false;
Steven Moreland44cd9482018-01-04 16:24:13 -08001432 {
1433 auto fd = android::base::unique_fd(
1434 TEMP_FAILURE_RETRY(open(path.c_str(),
1435 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1436 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1437 if (fd < 0) {
1438 MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str());
1439 continue;
1440 }
1441 RunCommandToFd(fd,
1442 "",
Steven Morelandc81cd3c2018-01-18 14:36:26 -08001443 {"lshal", "debug", "-E", interface},
Steven Moreland44cd9482018-01-04 16:24:13 -08001444 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1445
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001446 empty = 0 == lseek(fd, 0, SEEK_END);
Steven Moreland44cd9482018-01-04 16:24:13 -08001447 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001448 if (!empty) {
1449 ds.EnqueueAddZipEntryAndCleanupIfNeeded("lshal-debug/" + cleanName + ".txt",
1450 path);
1451 } else {
1452 unlink(path.c_str());
1453 }
Steven Moreland44cd9482018-01-04 16:24:13 -08001454 }
1455 });
1456
1457 if (!ret.isOk()) {
1458 MYLOGE("Could not list hals from hwservicemanager.\n");
1459 }
1460}
1461
Devin Moore8df81bb2022-06-08 22:47:02 +00001462// Dump all of the files that make up the vendor interface.
1463// See the files listed in dumpFileList() for the latest list of files.
1464static void DumpVintf() {
Devin Moore16271d92022-09-22 18:28:48 +00001465
1466 const std::string sku = android::base::GetProperty("ro.boot.product.hardware.sku", "");
1467 const auto vintfFiles = android::vintf::details::dumpFileList(sku);
Devin Moore8df81bb2022-06-08 22:47:02 +00001468 for (const auto vintfFile : vintfFiles) {
1469 struct stat st;
1470 if (stat(vintfFile.c_str(), &st) == 0) {
1471 if (S_ISDIR(st.st_mode)) {
1472 ds.AddDir(vintfFile, true /* recursive */);
1473 } else {
1474 ds.EnqueueAddZipEntryAndCleanupIfNeeded(ZIP_ROOT_DIR + vintfFile,
1475 vintfFile);
1476 }
1477 }
1478 }
1479}
1480
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001481static void DumpExternalFragmentationInfo() {
1482 struct stat st;
1483 if (stat("/proc/buddyinfo", &st) != 0) {
1484 MYLOGE("Unable to dump external fragmentation info\n");
1485 return;
1486 }
1487
1488 printf("------ EXTERNAL FRAGMENTATION INFO ------\n");
1489 std::ifstream ifs("/proc/buddyinfo");
1490 auto unusable_index_regex = std::regex{"Node\\s+([0-9]+),\\s+zone\\s+(\\S+)\\s+(.*)"};
1491 for (std::string line; std::getline(ifs, line);) {
1492 std::smatch match_results;
1493 if (std::regex_match(line, match_results, unusable_index_regex)) {
1494 std::stringstream free_pages(std::string{match_results[3]});
1495 std::vector<int> free_pages_per_order(std::istream_iterator<int>{free_pages},
1496 std::istream_iterator<int>());
1497
1498 int total_free_pages = 0;
1499 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1500 total_free_pages += (free_pages_per_order[i] * std::pow(2, i));
1501 }
1502
1503 printf("Node %s, zone %8s", match_results[1].str().c_str(),
1504 match_results[2].str().c_str());
1505
1506 int usable_free_pages = total_free_pages;
1507 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1508 auto unusable_index = (total_free_pages - usable_free_pages) /
1509 static_cast<double>(total_free_pages);
1510 printf(" %5.3f", unusable_index);
1511 usable_free_pages -= (free_pages_per_order[i] * std::pow(2, i));
1512 }
1513
1514 printf("\n");
1515 }
1516 }
1517 printf("\n");
1518}
1519
mhasankd451a472020-05-26 18:02:39 -07001520static void DumpstateLimitedOnly() {
EdenSue8fe4522023-11-20 15:37:23 +08001521 // Trimmed-down version of dumpstate to only include a allowlisted
mhasankd451a472020-05-26 18:02:39 -07001522 // set of logs (system log, event log, and system server / system app
1523 // crashes, and networking logs). See b/136273873 and b/138459828
1524 // for context.
1525 DurationReporter duration_reporter("DUMPSTATE");
1526 unsigned long timeout_ms;
1527 // calculate timeout
1528 timeout_ms = logcat_timeout({"main", "system", "crash"});
1529 RunCommand("SYSTEM LOG",
1530 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1531 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1532 timeout_ms = logcat_timeout({"events"});
1533 RunCommand(
1534 "EVENT LOG",
1535 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1536 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1537
1538 printf("========================================================\n");
1539 printf("== Networking Service\n");
1540 printf("========================================================\n");
1541
1542 RunDumpsys("DUMPSYS NETWORK_SERVICE_LIMITED", {"wifi", "-a"},
1543 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hugo Benichiaa162682020-10-30 23:28:56 +09001544 RunDumpsys("DUMPSYS CONNECTIVITY REQUESTS", {"connectivity", "requests"},
1545 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
mhasankd451a472020-05-26 18:02:39 -07001546
1547 printf("========================================================\n");
1548 printf("== Dropbox crashes\n");
1549 printf("========================================================\n");
1550
1551 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1552 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1553
1554 printf("========================================================\n");
1555 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1556 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1557 printf("========================================================\n");
1558 printf("== dumpstate: done (id %d)\n", ds.id_);
1559 printf("========================================================\n");
1560}
1561
Rhed Jaoe017f982020-07-21 17:58:41 +08001562/*
1563 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1564 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1565 * if it's not running in the parallel task.
1566 */
1567static void DumpCheckins(int out_fd = STDOUT_FILENO) {
1568 dprintf(out_fd, "========================================================\n");
1569 dprintf(out_fd, "== Checkins\n");
1570 dprintf(out_fd, "========================================================\n");
1571
1572 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"}, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001573 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"}, out_fd);
1574 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"}, out_fd);
1575 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"}, out_fd);
1576 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"}, out_fd);
1577}
1578
1579/*
1580 * Runs dumpsys on activity service to dump all application activities, services
1581 * and providers in the device.
1582 *
1583 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1584 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1585 * if it's not running in the parallel task.
1586 */
1587static void DumpAppInfos(int out_fd = STDOUT_FILENO) {
1588 dprintf(out_fd, "========================================================\n");
1589 dprintf(out_fd, "== Running Application Activities\n");
1590 dprintf(out_fd, "========================================================\n");
1591
1592 // The following dumpsys internally collects output from running apps, so it can take a long
1593 // time. So let's extend the timeout.
1594
1595 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1596
1597 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1598
1599 dprintf(out_fd, "========================================================\n");
1600 dprintf(out_fd, "== Running Application Services (platform)\n");
1601 dprintf(out_fd, "========================================================\n");
1602
1603 RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
1604 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1605
1606 dprintf(out_fd, "========================================================\n");
1607 dprintf(out_fd, "== Running Application Services (non-platform)\n");
1608 dprintf(out_fd, "========================================================\n");
1609
1610 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1611 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1612
1613 dprintf(out_fd, "========================================================\n");
1614 dprintf(out_fd, "== Running Application Providers (platform)\n");
1615 dprintf(out_fd, "========================================================\n");
1616
1617 RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
Rhed Jaob049f182021-01-11 21:08:43 +08001618 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001619
1620 dprintf(out_fd, "========================================================\n");
1621 dprintf(out_fd, "== Running Application Providers (non-platform)\n");
1622 dprintf(out_fd, "========================================================\n");
1623
1624 RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1625 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1626}
1627
Nandana Dutt5c390032019-03-12 10:52:56 +00001628// Dumps various things. Returns early with status USER_CONSENT_DENIED if user denies consent
1629// via the consent they are shown. Ignores other errors that occur while running various
1630// commands. The consent checking is currently done around long running tasks, which happen to
1631// be distributed fairly evenly throughout the function.
Kean Mariotti306633e2022-09-05 16:30:47 +00001632Dumpstate::RunStatus Dumpstate::dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001633 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001634
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001635 // Enqueue slow functions into the thread pool, if the parallel run is enabled.
Aaron Huanga99452a2022-04-27 18:51:16 +08001636 std::future<std::string> dump_hals, dump_incident_report, dump_board, dump_checkins,
Kean Mariotti306633e2022-09-05 16:30:47 +00001637 dump_netstats_report, post_process_ui_traces;
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001638 if (ds.dump_pool_) {
1639 // Pool was shutdown in DumpstateDefaultAfterCritical method in order to
Kean Mariotti306633e2022-09-05 16:30:47 +00001640 // drop root user. Restarts it.
1641 ds.dump_pool_->start(/* thread_counts = */3);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001642
Chris Morinbc223142022-02-04 14:17:11 -08001643 dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
1644 dump_incident_report = ds.dump_pool_->enqueueTask(
1645 DUMP_INCIDENT_REPORT_TASK, &DumpIncidentReport);
Aaron Huanga99452a2022-04-27 18:51:16 +08001646 dump_netstats_report = ds.dump_pool_->enqueueTask(
1647 DUMP_NETSTATS_PROTO_TASK, &DumpNetstatsProto);
Chris Morinbc223142022-02-04 14:17:11 -08001648 dump_board = ds.dump_pool_->enqueueTaskWithFd(
1649 DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
1650 dump_checkins = ds.dump_pool_->enqueueTaskWithFd(DUMP_CHECKINS_TASK, &DumpCheckins, _1);
Kean Mariotti306633e2022-09-05 16:30:47 +00001651 post_process_ui_traces = ds.dump_pool_->enqueueTask(
1652 POST_PROCESS_UI_TRACES_TASK, &Dumpstate::MaybePostProcessUiTraces, &ds);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001653 }
1654
Nandana Dutt5c390032019-03-12 10:52:56 +00001655 // Dump various things. Note that anything that takes "long" (i.e. several seconds) should
1656 // check intermittently (if it's intrerruptable like a foreach on pids) and/or should be wrapped
1657 // in a consent check (via RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK).
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001658 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001659 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001660 DumpBlockStatFiles();
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001661 DumpFile("MEMORY INFO", "/proc/meminfo");
1662 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001663 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001664
Kevin Jeon947922b2022-09-21 00:29:18 +00001665 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "BUGREPORT_PROCDUMP", {"bugreport_procdump"},
1666 CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001667
Sunny Goyal35949782019-11-19 15:54:36 -08001668 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpVisibleWindowViews);
1669
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001670 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1671 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1672 DumpFile("SLAB INFO", "/proc/slabinfo");
1673 DumpFile("ZONEINFO", "/proc/zoneinfo");
1674 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1675 DumpFile("BUDDYINFO", "/proc/buddyinfo");
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001676 DumpExternalFragmentationInfo();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001677
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001678 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001679
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001680 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001681 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001682
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001683 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001684 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_hals));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001685 } else {
1686 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_HALS_TASK, DumpHals);
1687 }
Steven Moreland81b429e2017-01-31 19:50:46 -08001688
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001689 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001690 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001691 struct stat s;
1692 if (stat("/proc/modules", &s) != 0) {
1693 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1694 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001695 RunCommand("LSMOD", {"lsmod"});
Woody Linc198f252021-05-04 16:37:11 +08001696 RunCommand("MODULES INFO",
1697 {"sh", "-c", "cat /proc/modules | cut -d' ' -f1 | "
1698 " while read MOD ; do echo modinfo:$MOD ; modinfo $MOD ; "
1699 "done"}, CommandOptions::AS_ROOT);
Felipe Lemee4eca582016-06-10 17:48:08 -07001700 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001701
Tom Cherryb87dbfa2020-07-28 11:28:53 -07001702 if (android::base::GetBoolProperty("ro.logd.kernel", false)) {
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001703 DoKernelLogcat();
1704 } else {
1705 do_dmesg();
1706 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001707
Devin Moore8df81bb2022-06-08 22:47:02 +00001708 DumpVintf();
1709
Felipe Lemef0292972016-11-22 13:57:05 -08001710 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001711
Jeff Brown1dc94e32014-09-11 14:15:27 -07001712 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001713 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001714
Jack Yu5a6b2e22020-08-14 18:13:35 +08001715 /* Dump Nfc NCI logs */
1716 ds.AddDir("/data/misc/nfc/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001717
Paul Chang0d2aad72020-02-13 20:04:03 +08001718 if (ds.options_->do_screenshot && !ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001719 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001720 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001721 }
1722
Felipe Lemee184f662016-10-27 10:04:47 -07001723 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001724
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001725 MaybeAddSystemTraceToZip();
1726
Narayan Kamath8f788292017-05-25 13:20:39 +01001727 // NOTE: tombstones are always added as separate entries in the zip archive
1728 // and are not interspersed with the main report.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001729 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
Narayan Kamathbd863722017-06-01 18:50:12 +01001730 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001731 if (!tombstones_dumped) {
1732 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001733 }
1734
Jayachandran Ca94c7172017-06-10 15:08:12 -07001735 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001736
Lorenzo Colitti807f2dd2022-05-27 12:48:37 +09001737 RunDumpsys("EBPF MAP STATS", {"connectivity", "trafficcontroller"});
Chenbo Feng276a3b62018-08-07 11:44:49 -07001738
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001739 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001740
Woody Lin20767a92022-11-29 15:50:24 +08001741 DumpShutdownCheckpoints();
1742
Jayachandran Ca94c7172017-06-10 15:08:12 -07001743 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001744
1745 dump_route_tables();
1746
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001747 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1748 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1749 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001750
Nandana Dutt5c390032019-03-12 10:52:56 +00001751 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysHigh);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001752
Chiachang Wang668ede42021-05-17 17:14:20 +08001753 // The dump mechanism in connectivity is refactored due to modularization work. Connectivity can
1754 // only register with a default priority(NORMAL priority). Dumpstate has to call connectivity
1755 // dump with priority parameters to dump high priority information.
1756 RunDumpsys("SERVICE HIGH connectivity", {"connectivity", "--dump-priority", "HIGH"},
1757 CommandOptions::WithTimeout(10).Build());
1758
Elliott Hughes23ccc622017-02-28 10:14:22 -08001759 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001760
Joe Onoratod38bc3a2023-06-29 15:48:28 -07001761 DumpFile("SYSTEM BUILD-TIME RELEASE FLAGS", "/system/etc/build_flags.json");
1762 DumpFile("SYSTEM_EXT BUILD-TIME RELEASE FLAGS", "/system_ext/etc/build_flags.json");
1763 DumpFile("PRODUCT BUILD-TIME RELEASE FLAGS", "/product/etc/build_flags.json");
1764 DumpFile("VENDOR BUILD-TIME RELEASE FLAGS", "/vendor/etc/build_flags.json");
1765
Mårten Kongstad5ad813f2023-09-28 10:09:18 +02001766 RunCommand("ACONFIG FLAGS", {PRINT_FLAGS},
1767 CommandOptions::WithTimeout(10).Always().DropRoot().Build());
Joe Onoratod38bc3a2023-06-29 15:48:28 -07001768
Jin Qianf334d662017-10-10 14:41:37 -07001769 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001770
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001771 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001772
Colin Crossf45fa6b2012-03-26 12:38:26 -07001773 /* Binder state is expensive to look at as it uses a lot of memory. */
Hridya Valsaraju920ba712020-02-09 16:27:01 -08001774 std::string binder_logs_dir = access("/dev/binderfs/binder_logs", R_OK) ?
1775 "/sys/kernel/debug/binder" : "/dev/binderfs/binder_logs";
1776
1777 DumpFile("BINDER FAILED TRANSACTION LOG", binder_logs_dir + "/failed_transaction_log");
1778 DumpFile("BINDER TRANSACTION LOG", binder_logs_dir + "/transaction_log");
1779 DumpFile("BINDER TRANSACTIONS", binder_logs_dir + "/transactions");
1780 DumpFile("BINDER STATS", binder_logs_dir + "/stats");
1781 DumpFile("BINDER STATE", binder_logs_dir + "/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001782
Yifan Hongd90cc652020-02-08 16:52:02 -08001783 ds.AddDir(SNAPSHOTCTL_LOG_DIR, false);
1784
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001785 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001786 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_board));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001787 } else {
1788 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
1789 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001790
Steven Moreland7440ddb2016-12-15 16:13:39 -08001791 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001792 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1793 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001794 // su does not exist on user builds, so try running without it.
1795 // This way any implementations of vril-dump that do not require
1796 // root can run on user builds.
1797 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001798 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001799 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001800 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001801 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001802 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001803 }
1804
Felipe Lemed8b94e52016-12-08 10:21:44 -08001805 printf("========================================================\n");
1806 printf("== Android Framework Services\n");
1807 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001808
Nandana Dutt5c390032019-03-12 10:52:56 +00001809 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001810
Jack He91ff2fe2021-02-18 18:23:43 -08001811 /* Dump Bluetooth HCI logs after getting bluetooth_manager dumpsys */
1812 ds.AddDir("/data/misc/bluetooth/logs", true);
1813
Rhed Jaoe017f982020-07-21 17:58:41 +08001814 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001815 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_checkins));
Rhed Jaoe017f982020-07-21 17:58:41 +08001816 } else {
1817 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_CHECKINS_TASK, DumpCheckins);
1818 }
Dianne Hackborn02bea972013-06-26 18:59:09 -07001819
Rhed Jaoc5f7ec32020-12-22 22:11:08 +08001820 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpAppInfos);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001821
Adrian Roos8b397ab2017-04-04 16:35:44 -07001822 printf("========================================================\n");
1823 printf("== Dropbox crashes\n");
1824 printf("========================================================\n");
1825
1826 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1827 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1828
Felipe Lemed8b94e52016-12-08 10:21:44 -08001829 printf("========================================================\n");
1830 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1831 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1832 printf("========================================================\n");
1833 printf("== dumpstate: done (id %d)\n", ds.id_);
1834 printf("========================================================\n");
Bookatz38472142018-09-28 10:20:24 -07001835
1836 printf("========================================================\n");
1837 printf("== Obtaining statsd metadata\n");
1838 printf("========================================================\n");
1839 // This differs from the usual dumpsys stats, which is the stats report data.
1840 RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
Mike Ma5c267872019-08-21 11:31:34 -07001841
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +09001842 // Add linker configuration directory
1843 ds.AddDir(LINKERCONFIG_DIR, true);
1844
Li Li830179f2022-01-04 12:53:29 -08001845 /* Dump frozen cgroupfs */
1846 dump_frozen_cgroupfs();
Li Li2eedd412021-06-30 15:11:53 -07001847
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001848 if (ds.dump_pool_) {
Aaron Huanga99452a2022-04-27 18:51:16 +08001849 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_netstats_report));
1850 } else {
1851 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_NETSTATS_PROTO_TASK,
1852 DumpNetstatsProto);
1853 }
1854
1855 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001856 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_incident_report));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001857 } else {
1858 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_INCIDENT_REPORT_TASK,
1859 DumpIncidentReport);
1860 }
Mike Ma5c267872019-08-21 11:31:34 -07001861
Kean Mariotti306633e2022-09-05 16:30:47 +00001862 if (ds.dump_pool_) {
1863 WaitForTask(std::move(post_process_ui_traces));
1864 } else {
1865 RUN_SLOW_FUNCTION_AND_LOG(POST_PROCESS_UI_TRACES_TASK, MaybePostProcessUiTraces);
1866 }
1867
1868 MaybeAddUiTracesToZip();
1869
Nandana Dutt5c390032019-03-12 10:52:56 +00001870 return Dumpstate::RunStatus::OK;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001871}
1872
Nandana Dutt5c390032019-03-12 10:52:56 +00001873/*
1874 * Dumps state for the default case; drops root after it's no longer necessary.
1875 *
1876 * Returns RunStatus::OK if everything went fine.
1877 * Returns RunStatus::ERROR if there was an error.
1878 * Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport
1879 * with the caller.
1880 */
Jichao Lie89d9c12019-11-21 19:02:51 -08001881Dumpstate::RunStatus Dumpstate::DumpstateDefaultAfterCritical() {
Nandana Duttdb379fa2019-10-09 16:54:41 +01001882 // Capture first logcat early on; useful to take a snapshot before dumpstate logs take over the
1883 // buffer.
1884 DoLogcat();
1885 // Capture timestamp after first logcat to use in next logcat
1886 time_t logcat_ts = time(nullptr);
1887
Nandana Dutt4be45d12018-09-26 15:04:23 +01001888 /* collect stack traces from Dalvik and native processes (needs root) */
Chris Morinbc223142022-02-04 14:17:11 -08001889 std::future<std::string> dump_traces;
Rhed Jao5377d792020-07-16 17:37:39 +08001890 if (dump_pool_) {
1891 RETURN_IF_USER_DENIED_CONSENT();
1892 // One thread is enough since we only need to enqueue DumpTraces here.
1893 dump_pool_->start(/* thread_counts = */1);
1894
1895 // DumpTraces takes long time, post it to the another thread in the
1896 // pool, if pool is available
Chris Morinbc223142022-02-04 14:17:11 -08001897 dump_traces = dump_pool_->enqueueTask(
1898 DUMP_TRACES_TASK, &Dumpstate::DumpTraces, &ds, &dump_traces_path);
Rhed Jao5377d792020-07-16 17:37:39 +08001899 } else {
1900 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_TRACES_TASK, ds.DumpTraces,
1901 &dump_traces_path);
1902 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001903
1904 /* Run some operations that require root. */
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001905 if (!PropertiesHelper::IsDryRun()) {
Chris Morinc2cba7a2022-02-01 17:06:50 -08001906 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX);
1907 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX);
Woody Lin20767a92022-11-29 15:50:24 +08001908 ds.shutdown_checkpoints_ = GetDumpFds(
1909 SHUTDOWN_CHECKPOINTS_DIR, SHUTDOWN_CHECKPOINTS_FILE_PREFIX);
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001910 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001911
1912 ds.AddDir(RECOVERY_DIR, true);
1913 ds.AddDir(RECOVERY_DATA_DIR, true);
1914 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
Kelvin Zhang6eaa0f92022-09-12 09:29:19 -07001915 ds.AddDir(UPDATE_ENGINE_PREF_DIR, true);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001916 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1917 if (!PropertiesHelper::IsUserBuild()) {
1918 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1919 ds.AddDir(PROFILE_DATA_DIR_REF, true);
Calin Juravlef84d3692020-04-28 15:31:12 -07001920 ds.AddZipEntry(ZIP_ROOT_DIR + PACKAGE_DEX_USE_LIST, PACKAGE_DEX_USE_LIST);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001921 }
Jerry Changa1df8a92020-01-02 16:03:39 +08001922 ds.AddDir(PREREBOOT_DATA_DIR, false);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001923 add_mountinfo();
Peter Collingbourne78aa2942023-02-15 14:50:31 -08001924 for (const char* path : {"/proc/cpuinfo", "/proc/meminfo"}) {
1925 ds.AddZipEntry(ZIP_ROOT_DIR + path, path);
1926 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001927 DumpIpTablesAsRoot();
David Andersond9ba4752018-12-11 18:26:59 -08001928 DumpDynamicPartitionInfo();
Yifan Hong3945e1b2019-10-29 12:59:23 -07001929 ds.AddDir(OTA_METADATA_DIR, true);
Jeff Sharkey9df29d52023-02-06 14:26:30 -07001930 if (!PropertiesHelper::IsUserBuild()) {
1931 // Include dropbox entry files inside ZIP, but exclude
1932 // noisy WTF and StrictMode entries
1933 dump_files("", DROPBOX_DIR, skip_wtf_strictmode, _add_file_from_fd);
1934 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001935
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001936 // Capture any IPSec policies in play. No keys are exposed here.
Nandana Dutt4be45d12018-09-26 15:04:23 +01001937 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1938
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001939 // Dump IPsec stats. No keys are exposed here.
1940 DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
1941
Nandana Dutt4be45d12018-09-26 15:04:23 +01001942 // Run ss as root so we can see socket marks.
1943 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1944
1945 // Run iotop as root to show top 100 IO threads
1946 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1947
Erick Reyese68df822019-02-11 14:46:36 -08001948 // Gather shared memory buffer info if the product implements it
Hridya Valsaraju1da80c52021-01-09 22:10:11 -08001949 RunCommand("Dmabuf dump", {"dmabuf_dump"});
1950 RunCommand("Dmabuf per-buffer/per-exporter/per-device stats", {"dmabuf_dump", "-b"});
Erick Reyese68df822019-02-11 14:46:36 -08001951
Minchan Kim22c6a1e2019-09-30 15:58:10 -07001952 DumpFile("PSI cpu", "/proc/pressure/cpu");
1953 DumpFile("PSI memory", "/proc/pressure/memory");
1954 DumpFile("PSI io", "/proc/pressure/io");
1955
Steven Moreland9379c462023-12-21 02:04:27 +00001956 ds.AddZipEntry(ZIP_ROOT_DIR + KERNEL_CONFIG, KERNEL_CONFIG);
1957
Mårten Kongstad60195a72022-09-20 14:14:20 +02001958 RunCommand("SDK EXTENSIONS", {SDK_EXT_INFO, "--dump"},
1959 CommandOptions::WithTimeout(10).Always().DropRoot().Build());
1960
Rhed Jao5377d792020-07-16 17:37:39 +08001961 if (dump_pool_) {
1962 RETURN_IF_USER_DENIED_CONSENT();
Chris Morinbc223142022-02-04 14:17:11 -08001963 WaitForTask(std::move(dump_traces));
Rhed Jao5377d792020-07-16 17:37:39 +08001964
Chris Morinbc223142022-02-04 14:17:11 -08001965 // Current running thread in the pool is the root user also. Delete
1966 // the pool and make a new one later to ensure none of threads in the pool are root.
1967 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao5377d792020-07-16 17:37:39 +08001968 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001969 if (!DropRootUser()) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001970 return Dumpstate::RunStatus::ERROR;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001971 }
1972
Nandana Dutt5c390032019-03-12 10:52:56 +00001973 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttdb379fa2019-10-09 16:54:41 +01001974 Dumpstate::RunStatus status = dumpstate();
1975 // Capture logcat since the last time we did it.
1976 DoSystemLogcat(logcat_ts);
1977 return status;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001978}
1979
Rhed Jaob5685b32020-08-14 17:19:17 +08001980// Common states for telephony and wifi which are needed to be collected before
1981// dumpstate drop the root user.
1982static void DumpstateRadioAsRoot() {
1983 DumpIpTablesAsRoot();
1984 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1985}
1986
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001987// This method collects common dumpsys for telephony and wifi. Typically, wifi
1988// reports are fine to include all information, but telephony reports on user
1989// builds need to strip some content (see DumpstateTelephonyOnly).
1990static void DumpstateRadioCommon(bool include_sensitive_info = true) {
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001991 // We need to be picky about some stuff for telephony reports on user builds.
1992 if (!include_sensitive_info) {
1993 // Only dump the radio log buffer (other buffers and dumps contain too much unrelated info).
1994 DoRadioLogcat();
1995 } else {
Rhed Jaob5685b32020-08-14 17:19:17 +08001996 // DumpHals takes long time, post it to the another thread in the pool,
1997 // if pool is available.
Chris Morinbc223142022-02-04 14:17:11 -08001998 std::future<std::string> dump_hals;
Rhed Jaob5685b32020-08-14 17:19:17 +08001999 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002000 dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
Rhed Jaob5685b32020-08-14 17:19:17 +08002001 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002002 // Contains various system properties and process startup info.
2003 do_dmesg();
2004 // Logs other than the radio buffer may contain package/component names and potential PII.
2005 DoLogcat();
2006 // Too broad for connectivity problems.
2007 DoKmsg();
Rhed Jaob5685b32020-08-14 17:19:17 +08002008 // DumpHals contains unrelated hardware info (camera, NFC, biometrics, ...).
2009 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002010 WaitForTask(std::move(dump_hals));
Rhed Jaob5685b32020-08-14 17:19:17 +08002011 } else {
2012 RUN_SLOW_FUNCTION_AND_LOG(DUMP_HALS_TASK, DumpHals);
2013 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002014 }
2015
Jayachandran Ca94c7172017-06-10 15:08:12 -07002016 DumpPacketStats();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002017 DumpIpAddrAndRules();
2018 dump_route_tables();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002019 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
2020 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08002021}
2022
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002023// We use "telephony" here for legacy reasons, though this now really means "connectivity" (cellular
2024// + wifi + networking). This method collects dumpsys for connectivity debugging only. General rules
2025// for what can be included on user builds: all reported information MUST directly relate to
2026// connectivity debugging or customer support and MUST NOT contain unrelated personally identifiable
2027// information. This information MUST NOT identify user-installed packages (UIDs are OK, package
2028// names are not), and MUST NOT contain logs of user application traffic.
2029// TODO(b/148168577) rename this and other related fields/methods to "connectivity" instead.
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08002030static void DumpstateTelephonyOnly(const std::string& calling_package) {
mukesh agrawal253dad42018-01-23 21:59:59 -08002031 DurationReporter duration_reporter("DUMPSTATE");
Jichao Lie89d9c12019-11-21 19:02:51 -08002032
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002033 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
mukesh agrawal253dad42018-01-23 21:59:59 -08002034
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002035 const bool include_sensitive_info = !PropertiesHelper::IsUserBuild();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002036
Rhed Jaob5685b32020-08-14 17:19:17 +08002037 DumpstateRadioAsRoot();
2038 if (!DropRootUser()) {
2039 return;
2040 }
2041
2042 // Starts thread pool after the root user is dropped, and two additional threads
2043 // are created for DumpHals in the DumpstateRadioCommon and DumpstateBoard.
Chris Morinbc223142022-02-04 14:17:11 -08002044 std::future<std::string> dump_board;
Rhed Jaob5685b32020-08-14 17:19:17 +08002045 if (ds.dump_pool_) {
2046 ds.dump_pool_->start(/*thread_counts =*/2);
2047
2048 // DumpstateBoard takes long time, post it to the another thread in the pool,
2049 // if pool is available.
Chris Morinbc223142022-02-04 14:17:11 -08002050 dump_board = ds.dump_pool_->enqueueTaskWithFd(
2051 DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
Rhed Jaob5685b32020-08-14 17:19:17 +08002052 }
2053
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002054 DumpstateRadioCommon(include_sensitive_info);
2055
2056 if (include_sensitive_info) {
2057 // Contains too much unrelated PII, and given the unstructured nature of sysprops, we can't
2058 // really cherrypick all of the connectivity-related ones. Apps generally have no business
2059 // reading these anyway, and there should be APIs to supply the info in a more app-friendly
2060 // way.
2061 RunCommand("SYSTEM PROPERTIES", {"getprop"});
2062 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002063
2064 printf("========================================================\n");
2065 printf("== Android Framework Services\n");
2066 printf("========================================================\n");
2067
Vishnu Nair652cc802017-11-30 15:18:30 -08002068 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2069 SEC_TO_MSEC(10));
Hunter Knepshield31cbae12021-05-11 16:23:24 -07002070 RunDumpsys("DUMPSYS", {"vcn_management"}, CommandOptions::WithTimeout(90).Build(),
2071 SEC_TO_MSEC(10));
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08002072 if (include_sensitive_info) {
2073 // Carrier apps' services will be dumped below in dumpsys activity service all-non-platform.
2074 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
2075 SEC_TO_MSEC(10));
2076 } else {
2077 // If the caller is a carrier app and has a carrier service, dump it here since we aren't
2078 // running dumpsys activity service all-non-platform below. Due to the increased output, we
2079 // give a higher timeout as well.
2080 RunDumpsys("DUMPSYS", {"carrier_config", "--requesting-package", calling_package},
2081 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(30));
2082 }
2083 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002084 RunDumpsys("DUMPSYS", {"netpolicy"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2085 RunDumpsys("DUMPSYS", {"network_management"}, CommandOptions::WithTimeout(90).Build(),
Sooraj Sasindrane8d98912018-04-20 11:31:55 -07002086 SEC_TO_MSEC(10));
Hunter Knepshield0fe51b12020-03-05 16:58:20 -08002087 RunDumpsys("DUMPSYS", {"telephony.registry"}, CommandOptions::WithTimeout(90).Build(),
2088 SEC_TO_MSEC(10));
Jack Yu773cc032023-03-16 22:43:39 -07002089 RunDumpsys("DUMPSYS", {"isub"}, CommandOptions::WithTimeout(90).Build(),
2090 SEC_TO_MSEC(10));
Grant Menke9bf3b2b2023-02-24 13:11:07 -08002091 RunDumpsys("DUMPSYS", {"telecom"}, CommandOptions::WithTimeout(90).Build(),
2092 SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002093 if (include_sensitive_info) {
2094 // Contains raw IP addresses, omit from reports on user builds.
2095 RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2096 // Contains raw destination IP/MAC addresses, omit from reports on user builds.
2097 RunDumpsys("DUMPSYS", {"connmetrics"}, CommandOptions::WithTimeout(90).Build(),
2098 SEC_TO_MSEC(10));
2099 // Contains package/component names, omit from reports on user builds.
2100 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
2101 SEC_TO_MSEC(10));
2102 // Contains package names, but should be relatively simple to remove them (also contains
2103 // UIDs already), omit from reports on user builds.
2104 RunDumpsys("BATTERYSTATS", {"deviceidle"}, CommandOptions::WithTimeout(90).Build(),
2105 SEC_TO_MSEC(10));
2106 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002107
2108 printf("========================================================\n");
2109 printf("== Running Application Services\n");
2110 printf("========================================================\n");
2111
2112 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
2113
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002114 if (include_sensitive_info) {
2115 printf("========================================================\n");
2116 printf("== Running Application Services (non-platform)\n");
2117 printf("========================================================\n");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002118
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002119 // Contains package/component names and potential PII, omit from reports on user builds.
2120 // To get dumps of the active CarrierService(s) on user builds, we supply an argument to the
2121 // carrier_config dumpsys instead.
2122 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
2123 DUMPSYS_COMPONENTS_OPTIONS);
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002124
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002125 printf("========================================================\n");
2126 printf("== Checkins\n");
2127 printf("========================================================\n");
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002128
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002129 // Contains package/component names, omit from reports on user builds.
2130 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
2131 }
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002132
2133 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07002134 printf("== dumpstate: done (id %d)\n", ds.id_);
2135 printf("========================================================\n");
Rhed Jaob5685b32020-08-14 17:19:17 +08002136
2137 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002138 WaitForTask(std::move(dump_board));
Rhed Jaob5685b32020-08-14 17:19:17 +08002139 } else {
2140 RUN_SLOW_FUNCTION_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
2141 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002142}
2143
mukesh agrawal253dad42018-01-23 21:59:59 -08002144// This method collects dumpsys for wifi debugging only
2145static void DumpstateWifiOnly() {
2146 DurationReporter duration_reporter("DUMPSTATE");
2147
Rhed Jaob5685b32020-08-14 17:19:17 +08002148 DumpstateRadioAsRoot();
2149 if (!DropRootUser()) {
2150 return;
2151 }
2152
2153 // Starts thread pool after the root user is dropped. Only one additional
2154 // thread is needed for DumpHals in the DumpstateRadioCommon.
2155 if (ds.dump_pool_) {
2156 ds.dump_pool_->start(/*thread_counts =*/1);
2157 }
2158
mukesh agrawal253dad42018-01-23 21:59:59 -08002159 DumpstateRadioCommon();
2160
2161 printf("========================================================\n");
2162 printf("== Android Framework Services\n");
2163 printf("========================================================\n");
2164
2165 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2166 SEC_TO_MSEC(10));
2167 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
2168 SEC_TO_MSEC(10));
2169
2170 printf("========================================================\n");
2171 printf("== dumpstate: done (id %d)\n", ds.id_);
2172 printf("========================================================\n");
2173}
2174
Nandana Duttcf419a72019-03-14 10:40:17 +00002175Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
Gavin Corkery789d7a52021-02-24 23:52:35 +00002176 const std::string temp_file_pattern = ds.bugreport_internal_dir_ + "/dumptrace_XXXXXX";
Nandana Duttfaafd522019-03-11 09:23:09 +00002177 const size_t buf_size = temp_file_pattern.length() + 1;
2178 std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
2179 memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
2180
2181 // Create a new, empty file to receive all trace dumps.
2182 //
2183 // TODO: This can be simplified once we remove support for the old style
2184 // dumps. We can have a file descriptor passed in to dump_traces instead
2185 // of creating a file, closing it and then reopening it again.
2186 android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
2187 if (fd < 0) {
2188 MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002189 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002190 }
2191
2192 // Nobody should have access to this temporary file except dumpstate, but we
2193 // temporarily grant 'read' to 'others' here because this file is created
2194 // when tombstoned is still running as root, but dumped after dropping. This
2195 // can go away once support for old style dumping has.
2196 const int chmod_ret = fchmod(fd, 0666);
2197 if (chmod_ret < 0) {
2198 MYLOGE("fchmod on %s failed: %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 std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
2203 if (proc.get() == nullptr) {
2204 MYLOGE("opendir /proc failed: %s\n", strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002205 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002206 }
2207
2208 // Number of times process dumping has timed out. If we encounter too many
2209 // failures, we'll give up.
2210 int timeout_failures = 0;
2211 bool dalvik_found = false;
2212
Jayant Chowdharya0a8eb22022-05-20 03:30:09 +00002213 const std::set<int> hal_pids = get_interesting_pids();
Nandana Duttfaafd522019-03-11 09:23:09 +00002214
2215 struct dirent* d;
2216 while ((d = readdir(proc.get()))) {
Nandana Duttcf419a72019-03-14 10:40:17 +00002217 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttfaafd522019-03-11 09:23:09 +00002218 int pid = atoi(d->d_name);
2219 if (pid <= 0) {
2220 continue;
2221 }
2222
Kevin Jeond0f8a982023-04-07 14:27:11 -04002223 // Skip cached processes.
2224 if (IsCached(pid)) {
2225 // For consistency, the header and footer to this message match those
2226 // dumped by debuggerd in the success case.
2227 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
2228 dprintf(fd, "Dump skipped for cached process.\n");
2229 dprintf(fd, "---- end %d ----", pid);
2230 continue;
2231 }
2232
Nandana Duttfaafd522019-03-11 09:23:09 +00002233 const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
2234 std::string exe;
2235 if (!android::base::Readlink(link_name, &exe)) {
2236 continue;
2237 }
2238
2239 bool is_java_process;
2240 if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
2241 // Don't bother dumping backtraces for the zygote.
2242 if (IsZygote(pid)) {
2243 continue;
2244 }
2245
2246 dalvik_found = true;
2247 is_java_process = true;
2248 } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
2249 is_java_process = false;
2250 } else {
2251 // Probably a native process we don't care about, continue.
2252 continue;
2253 }
2254
2255 // If 3 backtrace dumps fail in a row, consider debuggerd dead.
2256 if (timeout_failures == 3) {
2257 dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
2258 break;
2259 }
2260
2261 const uint64_t start = Nanotime();
2262 const int ret = dump_backtrace_to_file_timeout(
Kevin Jeonb8a39362023-04-04 15:00:34 -04002263 pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace, 3, fd);
Nandana Duttfaafd522019-03-11 09:23:09 +00002264
2265 if (ret == -1) {
2266 // For consistency, the header and footer to this message match those
2267 // dumped by debuggerd in the success case.
2268 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
2269 dprintf(fd, "Dump failed, likely due to a timeout.\n");
2270 dprintf(fd, "---- end %d ----", pid);
2271 timeout_failures++;
2272 continue;
2273 }
2274
2275 // We've successfully dumped stack traces, reset the failure count
2276 // and write a summary of the elapsed time to the file and continue with the
2277 // next process.
2278 timeout_failures = 0;
2279
2280 dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
2281 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
2282 }
2283
2284 if (!dalvik_found) {
2285 MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
2286 }
2287
Nandana Duttcf419a72019-03-14 10:40:17 +00002288 *path = file_name_buf.release();
2289 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002290}
2291
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002292static dumpstate_hal_hidl::DumpstateMode GetDumpstateHalModeHidl(
2293 const Dumpstate::BugreportMode bugreport_mode) {
2294 switch (bugreport_mode) {
2295 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2296 return dumpstate_hal_hidl::DumpstateMode::FULL;
2297 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2298 return dumpstate_hal_hidl::DumpstateMode::INTERACTIVE;
2299 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2300 return dumpstate_hal_hidl::DumpstateMode::REMOTE;
2301 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2302 return dumpstate_hal_hidl::DumpstateMode::WEAR;
2303 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2304 return dumpstate_hal_hidl::DumpstateMode::CONNECTIVITY;
2305 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2306 return dumpstate_hal_hidl::DumpstateMode::WIFI;
2307 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2308 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2309 }
2310 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2311}
2312
2313static dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode GetDumpstateHalModeAidl(
2314 const Dumpstate::BugreportMode bugreport_mode) {
2315 switch (bugreport_mode) {
2316 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2317 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::FULL;
2318 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2319 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::INTERACTIVE;
2320 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2321 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::REMOTE;
2322 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2323 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WEAR;
2324 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2325 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::CONNECTIVITY;
2326 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2327 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WIFI;
2328 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2329 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2330 }
2331 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2332}
2333
2334static void DoDumpstateBoardHidl(
2335 const sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_1_0,
2336 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2337 const Dumpstate::BugreportMode bugreport_mode,
2338 const size_t timeout_sec) {
2339
2340 using ScopedNativeHandle =
2341 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
2342 ScopedNativeHandle handle(native_handle_create(static_cast<int>(dumpstate_fds.size()), 0),
2343 [](native_handle_t* handle) {
2344 // we don't close file handle's here
2345 // via native_handle_close(handle)
2346 // instead we let dumpstate_fds close the file handles when
2347 // dumpstate_fds gets destroyed
2348 native_handle_delete(handle);
2349 });
2350 if (handle == nullptr) {
2351 MYLOGE("Could not create native_handle for dumpstate HAL\n");
2352 return;
2353 }
2354
2355 for (size_t i = 0; i < dumpstate_fds.size(); i++) {
2356 handle.get()->data[i] = dumpstate_fds[i].get();
2357 }
2358
2359 // Prefer version 1.1 if available. New devices launching with R are no longer allowed to
2360 // implement just 1.0.
2361 const char* descriptor_to_kill;
2362 using DumpstateBoardTask = std::packaged_task<bool()>;
2363 DumpstateBoardTask dumpstate_board_task;
2364 sp<dumpstate_hal_hidl::IDumpstateDevice> dumpstate_hal(
2365 dumpstate_hal_hidl::IDumpstateDevice::castFrom(dumpstate_hal_1_0));
2366 if (dumpstate_hal != nullptr) {
2367 MYLOGI("Using IDumpstateDevice v1.1 HIDL HAL");
2368
2369 dumpstate_hal_hidl::DumpstateMode dumpstate_hal_mode =
2370 GetDumpstateHalModeHidl(bugreport_mode);
2371
2372 descriptor_to_kill = dumpstate_hal_hidl::IDumpstateDevice::descriptor;
2373 dumpstate_board_task =
2374 DumpstateBoardTask([timeout_sec, dumpstate_hal_mode, dumpstate_hal, &handle]() -> bool {
2375 ::android::hardware::Return<dumpstate_hal_hidl::DumpstateStatus> status =
2376 dumpstate_hal->dumpstateBoard_1_1(handle.get(), dumpstate_hal_mode,
2377 SEC_TO_MSEC(timeout_sec));
2378 if (!status.isOk()) {
2379 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2380 return false;
2381 } else if (status != dumpstate_hal_hidl::DumpstateStatus::OK) {
2382 MYLOGE("dumpstateBoard failed with DumpstateStatus::%s\n",
2383 dumpstate_hal_hidl::toString(status).c_str());
2384 return false;
2385 }
2386 return true;
2387 });
2388 } else {
2389 MYLOGI("Using IDumpstateDevice v1.0 HIDL HAL");
2390
2391 descriptor_to_kill = dumpstate_hal_hidl_1_0::IDumpstateDevice::descriptor;
2392 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal_1_0, &handle]() -> bool {
2393 ::android::hardware::Return<void> status =
2394 dumpstate_hal_1_0->dumpstateBoard(handle.get());
2395 if (!status.isOk()) {
2396 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2397 return false;
2398 }
2399 return true;
2400 });
2401 }
2402 auto result = dumpstate_board_task.get_future();
2403 std::thread(std::move(dumpstate_board_task)).detach();
2404
2405 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2406 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2407 if (!android::base::SetProperty(
2408 "ctl.interface_restart",
2409 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2410 MYLOGE("Couldn't restart dumpstate HAL\n");
2411 }
2412 }
2413 // Wait some time for init to kill dumpstate vendor HAL
2414 constexpr size_t killing_timeout_sec = 10;
2415 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2416 MYLOGE(
2417 "killing dumpstateBoard timed out after %zus, continue and "
2418 "there might be racing in content\n",
2419 killing_timeout_sec);
2420 }
2421}
2422
2423static void DoDumpstateBoardAidl(
2424 const std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal,
2425 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2426 const Dumpstate::BugreportMode bugreport_mode, const size_t timeout_sec) {
2427 MYLOGI("Using IDumpstateDevice AIDL HAL");
2428
2429 const char* descriptor_to_kill;
2430 using DumpstateBoardTask = std::packaged_task<bool()>;
2431 DumpstateBoardTask dumpstate_board_task;
2432 dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode dumpstate_hal_mode =
2433 GetDumpstateHalModeAidl(bugreport_mode);
2434
2435 descriptor_to_kill = dumpstate_hal_aidl::IDumpstateDevice::descriptor;
2436 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal, &dumpstate_fds, dumpstate_hal_mode,
2437 timeout_sec]() -> bool {
2438 auto status = dumpstate_hal->dumpstateBoard(dumpstate_fds, dumpstate_hal_mode, timeout_sec);
2439
2440 if (!status.isOk()) {
2441 MYLOGE("dumpstateBoard failed: %s\n", status.getDescription().c_str());
2442 return false;
2443 }
2444 return true;
2445 });
2446 auto result = dumpstate_board_task.get_future();
2447 std::thread(std::move(dumpstate_board_task)).detach();
2448
2449 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2450 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2451 if (!android::base::SetProperty(
2452 "ctl.interface_restart",
2453 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2454 MYLOGE("Couldn't restart dumpstate HAL\n");
2455 }
2456 }
2457 // Wait some time for init to kill dumpstate vendor HAL
2458 constexpr size_t killing_timeout_sec = 10;
2459 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2460 MYLOGE(
2461 "killing dumpstateBoard timed out after %zus, continue and "
2462 "there might be racing in content\n",
2463 killing_timeout_sec);
2464 }
2465}
2466
2467static std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> GetDumpstateBoardAidlService() {
2468 const std::string aidl_instance_name =
2469 std::string(dumpstate_hal_aidl::IDumpstateDevice::descriptor) + "/default";
2470
2471 if (!AServiceManager_isDeclared(aidl_instance_name.c_str())) {
2472 return nullptr;
2473 }
2474
2475 ndk::SpAIBinder dumpstateBinder(AServiceManager_waitForService(aidl_instance_name.c_str()));
2476
2477 return dumpstate_hal_aidl::IDumpstateDevice::fromBinder(dumpstateBinder);
2478}
2479
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002480void Dumpstate::DumpstateBoard(int out_fd) {
2481 dprintf(out_fd, "========================================================\n");
2482 dprintf(out_fd, "== Board\n");
2483 dprintf(out_fd, "========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08002484
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002485 /*
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002486 * mount debugfs for non-user builds with ro.product.debugfs_restrictions.enabled
Hridya Valsaraju51101602021-04-02 14:32:46 -07002487 * set to true and unmount it after invoking dumpstateBoard_* methods.
2488 * This is to enable debug builds to not have debugfs mounted during runtime.
2489 * It will also ensure that debugfs is only accessed by the dumpstate HAL.
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002490 */
Hridya Valsaraju51101602021-04-02 14:32:46 -07002491 auto mount_debugfs =
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002492 android::base::GetBoolProperty("ro.product.debugfs_restrictions.enabled", false);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002493 if (mount_debugfs) {
2494 RunCommand("mount debugfs", {"mount", "-t", "debugfs", "debugfs", "/sys/kernel/debug"},
2495 AS_ROOT_20);
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002496 RunCommand("chmod debugfs", {"chmod", "0755", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002497 }
2498
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002499 std::vector<std::string> paths;
2500 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07002501 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002502 paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
2503 kDumpstateBoardFiles[i].c_str()));
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002504 remover.emplace_back(android::base::make_scope_guard(
2505 std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002506 }
Jie Song9fbfad02017-06-20 16:29:42 -07002507
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002508 // get dumpstate HAL AIDL implementation
2509 std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal_handle_aidl(
2510 GetDumpstateBoardAidlService());
2511 if (dumpstate_hal_handle_aidl == nullptr) {
2512 MYLOGI("No IDumpstateDevice AIDL implementation\n");
2513 }
2514
2515 // get dumpstate HAL HIDL implementation, only if AIDL HAL implementation not found
2516 sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_handle_hidl_1_0 = nullptr;
2517 if (dumpstate_hal_handle_aidl == nullptr) {
2518 dumpstate_hal_handle_hidl_1_0 = dumpstate_hal_hidl_1_0::IDumpstateDevice::getService();
2519 if (dumpstate_hal_handle_hidl_1_0 == nullptr) {
2520 MYLOGI("No IDumpstateDevice HIDL implementation\n");
2521 }
2522 }
2523
2524 // if neither HIDL nor AIDL implementation found, then return
2525 if (dumpstate_hal_handle_hidl_1_0 == nullptr && dumpstate_hal_handle_aidl == nullptr) {
2526 MYLOGE("Could not find IDumpstateDevice implementation\n");
Wei Wang587eac92018-04-05 12:17:20 -07002527 return;
2528 }
2529
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002530 // this is used to hold the file descriptors and when this variable goes out of scope
2531 // the file descriptors are closed
2532 std::vector<::ndk::ScopedFileDescriptor> dumpstate_fds;
Wei Wang587eac92018-04-05 12:17:20 -07002533
Nandana Dutt5c390032019-03-12 10:52:56 +00002534 // TODO(128270426): Check for consent in between?
Wei Wang587eac92018-04-05 12:17:20 -07002535 for (size_t i = 0; i < paths.size(); i++) {
2536 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
2537
2538 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
2539 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
2540 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
2541 if (fd < 0) {
2542 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
2543 return;
2544 }
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002545
2546 dumpstate_fds.emplace_back(fd.release());
2547 // we call fd.release() here to make sure "fd" does not get closed
2548 // after "fd" goes out of scope after this block.
2549 // "fd" will be closed when "dumpstate_fds" goes out of scope
2550 // i.e. when we exit this function
Wei Wang587eac92018-04-05 12:17:20 -07002551 }
2552
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002553 // Given that bugreport is required to diagnose failures, it's better to set an arbitrary amount
2554 // of timeout for IDumpstateDevice than to block the rest of bugreport. In the timeout case, we
2555 // will kill the HAL and grab whatever it dumped in time.
Michael Eastwood8523ea02022-03-10 16:33:08 -08002556 constexpr size_t timeout_sec = 45;
Wei Wang587eac92018-04-05 12:17:20 -07002557
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002558 if (dumpstate_hal_handle_aidl != nullptr) {
2559 DoDumpstateBoardAidl(dumpstate_hal_handle_aidl, dumpstate_fds, options_->bugreport_mode,
2560 timeout_sec);
2561 } else if (dumpstate_hal_handle_hidl_1_0 != nullptr) {
2562 // run HIDL HAL only if AIDL HAL not found
2563 DoDumpstateBoardHidl(dumpstate_hal_handle_hidl_1_0, dumpstate_fds, options_->bugreport_mode,
2564 timeout_sec);
Wei Wang587eac92018-04-05 12:17:20 -07002565 }
2566
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002567 if (mount_debugfs) {
Hridya Valsaraju51101602021-04-02 14:32:46 -07002568 auto keep_debugfs_mounted =
2569 android::base::GetProperty("persist.dbg.keep_debugfs_mounted", "");
2570 if (keep_debugfs_mounted.empty())
2571 RunCommand("unmount debugfs", {"umount", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002572 }
2573
Wei Wang587eac92018-04-05 12:17:20 -07002574 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
2575 for (size_t i = 0; i < paths.size(); i++) {
2576 struct stat s;
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002577 if (fstat(dumpstate_fds[i].get(), &s) == -1) {
2578 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(), strerror(errno));
Wei Wang587eac92018-04-05 12:17:20 -07002579 file_sizes[i] = -1;
2580 continue;
2581 }
2582 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002583 }
2584
2585 for (size_t i = 0; i < paths.size(); i++) {
2586 if (file_sizes[i] == -1) {
2587 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002588 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002589 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07002590 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002591 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002592 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002593 remover[i].Disable();
2594 EnqueueAddZipEntryAndCleanupIfNeeded(kDumpstateBoardFiles[i], paths[i]);
2595 dprintf(out_fd, "*** See %s entry ***\n", kDumpstateBoardFiles[i].c_str());
Jie Song9fbfad02017-06-20 16:29:42 -07002596 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08002597}
2598
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002599static void ShowUsage() {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002600 fprintf(stderr,
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002601 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o directory] [-p] "
2602 "[-s] [-S] [-q] [-P] [-R] [-L] [-V version]\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002603 " -h: display this help message\n"
2604 " -b: play sound file instead of vibrate, at beginning of job\n"
2605 " -e: play sound file instead of vibrate, at end of job\n"
mhasank2d75c442020-06-11 15:05:25 -07002606 " -o: write to custom directory (only in limited mode)\n"
Abhijeet Kaurbb55a3b2019-06-13 18:07:25 +01002607 " -p: capture screenshot to filename.png\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002608 " -s: write zipped file to control socket (for init)\n"
2609 " -S: write file location to control socket (for init)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002610 " -q: disable vibrate\n"
Abhijeet Kaure370d682019-10-01 16:49:30 +01002611 " -P: send broadcast when started and do progress updates\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002612 " -R: take bugreport in remote mode (shouldn't be used with -P)\n"
Nandana Dutt235864b2019-01-22 12:10:16 +00002613 " -w: start binder service and make it wait for a call to startBugreport\n"
mhasankd451a472020-05-26 18:02:39 -07002614 " -L: output limited information that is safe for submission in feedback reports\n"
Felipe Lemed071c682016-10-20 16:48:00 -07002615 " -v: prints the dumpstate header and exit\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002616}
2617
Wei Liuf87959e2016-08-26 14:51:42 -07002618static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07002619 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07002620}
2621
Felipe Leme1d486fe2016-10-14 18:06:47 -07002622bool Dumpstate::FinishZipFile() {
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002623 // Runs all enqueued adding zip entry and cleanup tasks before finishing the zip file.
2624 if (zip_entry_tasks_) {
2625 zip_entry_tasks_->run(/* do_cancel = */false);
2626 }
2627
Felipe Leme9a523ae2016-10-20 15:10:33 -07002628 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07002629 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07002630 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002631 // Final timestamp
2632 char date[80];
2633 time_t the_real_now_please_stand_up = time(nullptr);
2634 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002635 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002636 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002637
Felipe Leme9a523ae2016-10-20 15:10:33 -07002638 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002639 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08002640 return false;
2641 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07002642 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002643 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08002644 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08002645 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08002646
Felipe Leme0f3fb202016-06-10 17:10:53 -07002647 // Add log file (which contains stderr output) to zip...
2648 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002649 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07002650 MYLOGE("Failed to add dumpstate log to .zip file\n");
2651 return false;
2652 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002653 // TODO: Should truncate the existing file.
2654 // ... and re-open it for further logging.
Nandana Dutta344cb62019-02-22 15:12:35 +00002655 if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
2656 return false;
2657 }
Felipe Leme0f3fb202016-06-10 17:10:53 -07002658 fprintf(stderr, "\n");
2659
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002660 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07002661 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002662 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002663 return false;
2664 }
2665
Felipe Leme1d486fe2016-10-14 18:06:47 -07002666 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
2667 ds.zip_file.reset(nullptr);
2668
Felipe Lemee9d2c542016-11-15 11:48:26 -08002669 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002670 android::os::UnlinkAndLogOnError(tmp_path_);
Felipe Lemec4eee562016-04-21 15:42:55 -07002671
Felipe Leme1e9edc62015-12-21 16:02:13 -08002672 return true;
2673}
Felipe Leme6e01fa62015-11-11 19:35:14 -08002674
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00002675static void SendBroadcast(const std::string& action,
2676 const std::vector<std::string>& args,
2677 int32_t user_id) {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002678 // clang-format off
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00002679 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user",
2680 std::to_string(user_id), "--receiver-foreground",
2681 "--receiver-include-background", "-a", action};
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002682 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08002683
2684 am.insert(am.end(), args.begin(), args.end());
2685
Felipe Leme8d2410e2017-02-08 09:46:08 -08002686 RunCommand("", am,
2687 CommandOptions::WithTimeout(20)
2688 .Log("Sending broadcast: '%s'\n")
2689 .Always()
2690 .DropRoot()
2691 .RedirectStderr()
2692 .Build());
2693}
2694
Felipe Leme35b8cf12017-02-10 15:47:29 -08002695static void Vibrate(int duration_ms) {
2696 // clang-format off
Lais Andrade51156962021-02-22 19:21:35 +00002697 std::vector<std::string> args = {"cmd", "vibrator_manager", "synced", "-f", "-d", "dumpstate",
2698 "oneshot", std::to_string(duration_ms)};
2699 RunCommand("", args,
Felipe Leme35b8cf12017-02-10 15:47:29 -08002700 CommandOptions::WithTimeout(10)
2701 .Log("Vibrate: '%s'\n")
2702 .Always()
2703 .Build());
2704 // clang-format on
2705}
2706
Nandana Dutt979388e2018-11-30 16:48:55 +00002707static void MaybeResolveSymlink(std::string* path) {
2708 std::string resolved_path;
2709 if (android::base::Readlink(*path, &resolved_path)) {
2710 *path = resolved_path;
2711 }
2712}
2713
Nandana Dutt4be45d12018-09-26 15:04:23 +01002714/*
2715 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002716 * and adds the version file. Return false if zip_file could not be open to write.
Nandana Dutt4be45d12018-09-26 15:04:23 +01002717 */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002718static bool PrepareToWriteToFile() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002719 MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2720
Nandana Dutt4be45d12018-09-26 15:04:23 +01002721 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2722 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002723 ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002724 char date[80];
2725 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2726 ds.name_ = date;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002727
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002728 if (ds.options_->telephony_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002729 ds.base_name_ += "-telephony";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002730 } else if (ds.options_->wifi_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002731 ds.base_name_ += "-wifi";
2732 }
2733
Paul Chang0d2aad72020-02-13 20:04:03 +08002734 if (ds.options_->do_screenshot) {
Nandana Dutt9d17b942020-03-26 10:02:59 +00002735 ds.screenshot_path_ = ds.GetPath(ds.CalledByApi() ? "-png.tmp" : ".png");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002736 }
2737 ds.tmp_path_ = ds.GetPath(".tmp");
2738 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2739
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01002740 std::string destination = ds.CalledByApi()
Nandana Dutt54dbd672019-01-11 12:58:05 +00002741 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
Nandana Dutt9a76d202019-01-21 15:56:48 +00002742 : ds.bugreport_internal_dir_.c_str();
Nandana Dutt4be45d12018-09-26 15:04:23 +01002743 MYLOGD(
Nandana Dutt235c6672019-11-14 15:22:32 +00002744 "Bugreport dir: [%s] "
2745 "Base name: [%s] "
2746 "Suffix: [%s] "
2747 "Log path: [%s] "
2748 "Temporary path: [%s] "
2749 "Screenshot path: [%s]\n",
Nandana Dutt9a76d202019-01-21 15:56:48 +00002750 destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2751 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002752
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002753 ds.path_ = ds.GetPath(ds.CalledByApi() ? "-zip.tmp" : ".zip");
2754 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2755 create_parent_dirs(ds.path_.c_str());
2756 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2757 if (ds.zip_file == nullptr) {
2758 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2759 return false;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002760 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002761 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2762 ds.AddTextZipEntry("version.txt", ds.version_);
2763 return true;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002764}
2765
2766/*
Abhijeet Kaure370d682019-10-01 16:49:30 +01002767 * Finalizes writing to the file by zipping the tmp file to the final location,
Nandana Dutt4be45d12018-09-26 15:04:23 +01002768 * printing zipped file status, etc.
2769 */
2770static void FinalizeFile() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002771 bool do_text_file = !ds.FinishZipFile();
2772 if (do_text_file) {
2773 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002774 }
mhasank2d75c442020-06-11 15:05:25 -07002775
2776 std::string final_path = ds.path_;
2777 if (ds.options_->OutputToCustomFile()) {
mhasank3a4cfb42020-06-15 18:06:43 -07002778 final_path = ds.GetPath(ds.options_->out_dir, ".zip");
mhasank2d75c442020-06-11 15:05:25 -07002779 android::os::CopyFileToFile(ds.path_, final_path);
2780 }
2781
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002782 if (ds.options_->stream_to_socket) {
2783 android::os::CopyFileToFd(ds.path_, ds.control_socket_fd_);
2784 } else if (ds.options_->progress_updates_to_socket) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002785 if (do_text_file) {
2786 dprintf(ds.control_socket_fd_,
2787 "FAIL:could not create zip file, check %s "
2788 "for more details\n",
2789 ds.log_path_.c_str());
2790 } else {
mhasank2d75c442020-06-11 15:05:25 -07002791 dprintf(ds.control_socket_fd_, "OK:%s\n", final_path.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002792 }
2793 }
2794}
2795
Nandana Dutt4be45d12018-09-26 15:04:23 +01002796
Nandana Dutt58d72e22018-11-16 10:30:48 +00002797static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2798 switch (mode) {
2799 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2800 return "BUGREPORT_FULL";
2801 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2802 return "BUGREPORT_INTERACTIVE";
2803 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2804 return "BUGREPORT_REMOTE";
2805 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2806 return "BUGREPORT_WEAR";
2807 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2808 return "BUGREPORT_TELEPHONY";
2809 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2810 return "BUGREPORT_WIFI";
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002811 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2812 return "BUGREPORT_DEFAULT";
Nandana Dutt58d72e22018-11-16 10:30:48 +00002813 }
2814}
2815
Steven Leeb573eb82022-11-29 22:31:35 +08002816static bool IsConsentlessBugreportAllowed(const Dumpstate::DumpOptions& options) {
2817 // only BUGREPORT_TELEPHONY does not allow using consentless bugreport
2818 return !options.telephony_only;
2819}
2820
Paul Changf59c2b72020-03-10 02:08:55 +08002821static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options,
2822 bool is_screenshot_requested) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002823 // Modify com.android.shell.BugreportProgressService#isDefaultScreenshotRequired as well for
2824 // default system screenshots.
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002825 options->bugreport_mode = mode;
2826 options->bugreport_mode_string = ModeToString(mode);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002827 switch (mode) {
2828 case Dumpstate::BugreportMode::BUGREPORT_FULL:
Paul Changf59c2b72020-03-10 02:08:55 +08002829 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002830 break;
2831 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002832 // Currently, the dumpstate binder is only used by Shell to update progress.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002833 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002834 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002835 break;
2836 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002837 options->do_vibrate = false;
2838 options->is_remote_mode = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002839 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002840 break;
2841 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
Robert Ginda55ecebd2023-04-03 22:53:13 +00002842 options->do_vibrate = false;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002843 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002844 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002845 break;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002846 // TODO(b/148168577) rename TELEPHONY everywhere to CONNECTIVITY.
Nandana Dutt58d72e22018-11-16 10:30:48 +00002847 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002848 options->telephony_only = true;
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002849 options->do_progress_updates = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002850 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002851 break;
2852 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002853 options->wifi_only = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002854 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002855 break;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002856 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2857 break;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002858 }
2859}
2860
Nandana Dutt58d72e22018-11-16 10:30:48 +00002861static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
Nandana Dutt235c6672019-11-14 15:22:32 +00002862 MYLOGI(
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002863 "do_vibrate: %d stream_to_socket: %d progress_updates_to_socket: %d do_screenshot: %d "
Rhed Jao25f50e02020-08-20 00:10:32 +08002864 "is_remote_mode: %d show_header_only: %d telephony_only: %d "
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002865 "wifi_only: %d do_progress_updates: %d fd: %d bugreport_mode: %s "
mhasankd451a472020-05-26 18:02:39 -07002866 "limited_only: %d args: %s\n",
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002867 options.do_vibrate, options.stream_to_socket, options.progress_updates_to_socket,
Paul Chang0d2aad72020-02-13 20:04:03 +08002868 options.do_screenshot, options.is_remote_mode, options.show_header_only,
Rhed Jao25f50e02020-08-20 00:10:32 +08002869 options.telephony_only, options.wifi_only,
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002870 options.do_progress_updates, options.bugreport_fd.get(),
2871 options.bugreport_mode_string.c_str(),
2872 options.limited_only, options.args.c_str());
Nandana Dutt58d72e22018-11-16 10:30:48 +00002873}
2874
Nandana Dutt54dbd672019-01-11 12:58:05 +00002875void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
Kean Mariotti306633e2022-09-05 16:30:47 +00002876 int bugreport_flags,
Nandana Dutt54dbd672019-01-11 12:58:05 +00002877 const android::base::unique_fd& bugreport_fd_in,
Paul Changf59c2b72020-03-10 02:08:55 +08002878 const android::base::unique_fd& screenshot_fd_in,
2879 bool is_screenshot_requested) {
Kean Mariotti306633e2022-09-05 16:30:47 +00002880 this->use_predumped_ui_data = bugreport_flags & BugreportFlag::BUGREPORT_USE_PREDUMPED_UI_DATA;
Gavin Corkerya44686c2022-11-23 18:16:51 +00002881 this->is_consent_deferred = bugreport_flags & BugreportFlag::BUGREPORT_FLAG_DEFER_CONSENT;
Nandana Dutt54dbd672019-01-11 12:58:05 +00002882 // Duplicate the fds because the passed in fds don't outlive the binder transaction.
Todd Frederick621533f2022-03-26 02:54:17 +00002883 bugreport_fd.reset(fcntl(bugreport_fd_in.get(), F_DUPFD_CLOEXEC, 0));
2884 screenshot_fd.reset(fcntl(screenshot_fd_in.get(), F_DUPFD_CLOEXEC, 0));
Nandana Dutt58d72e22018-11-16 10:30:48 +00002885
Paul Changf59c2b72020-03-10 02:08:55 +08002886 SetOptionsFromMode(bugreport_mode, this, is_screenshot_requested);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002887}
2888
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002889Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
2890 RunStatus status = RunStatus::OK;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002891 int c;
mhasankd451a472020-05-26 18:02:39 -07002892 while ((c = getopt(argc, argv, "dho:svqzpLPBRSV:w")) != -1) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002893 switch (c) {
2894 // clang-format off
mhasank3a4cfb42020-06-15 18:06:43 -07002895 case 'o': out_dir = optarg; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002896 case 's': stream_to_socket = true; break;
2897 case 'S': progress_updates_to_socket = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002898 case 'v': show_header_only = true; break;
2899 case 'q': do_vibrate = false; break;
Paul Chang0d2aad72020-02-13 20:04:03 +08002900 case 'p': do_screenshot = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002901 case 'P': do_progress_updates = true; break;
2902 case 'R': is_remote_mode = true; break;
mhasankd451a472020-05-26 18:02:39 -07002903 case 'L': limited_only = true; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002904 case 'V':
2905 case 'd':
2906 case 'z':
2907 // compatibility no-op
2908 break;
Nandana Dutt235864b2019-01-22 12:10:16 +00002909 case 'w':
2910 // This was already processed
2911 break;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002912 case 'h':
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002913 status = RunStatus::HELP;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002914 break;
2915 default:
2916 fprintf(stderr, "Invalid option: %c\n", c);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002917 status = RunStatus::INVALID_INPUT;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002918 break;
2919 // clang-format on
2920 }
2921 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08002922
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002923 for (int i = 0; i < argc; i++) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002924 args += argv[i];
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002925 if (i < argc - 1) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002926 args += " ";
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002927 }
2928 }
2929
2930 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
2931 optind = 1;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002932
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002933 return status;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002934}
2935
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002936bool Dumpstate::DumpOptions::ValidateOptions() const {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002937 if (bugreport_fd.get() != -1 && stream_to_socket) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002938 return false;
2939 }
2940
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002941 if ((progress_updates_to_socket || do_progress_updates) && stream_to_socket) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002942 return false;
2943 }
2944
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002945 if (is_remote_mode && (do_progress_updates || stream_to_socket)) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002946 return false;
2947 }
2948 return true;
2949}
2950
Nandana Dutt197661d2018-11-16 16:40:21 +00002951void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
2952 options_ = std::move(options);
2953}
2954
Abhijeet Kaura407fb82020-03-27 12:51:12 +00002955void Dumpstate::Initialize() {
2956 /* gets the sequential id */
2957 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
2958 id_ = ++last_id;
2959 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
2960}
2961
Nandana Duttd2f5f082019-01-18 17:13:52 +00002962Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
2963 Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
Gavin Corkerya44686c2022-11-23 18:16:51 +00002964 HandleRunStatus(status);
2965 return status;
2966}
2967
2968Dumpstate::RunStatus Dumpstate::Retrieve(int32_t calling_uid, const std::string& calling_package) {
2969 Dumpstate::RunStatus status = RetrieveInternal(calling_uid, calling_package);
2970 HandleRunStatus(status);
2971 return status;
2972}
2973
2974Dumpstate::RunStatus Dumpstate::RetrieveInternal(int32_t calling_uid,
2975 const std::string& calling_package) {
2976 consent_callback_ = new ConsentCallback();
2977 const String16 incidentcompanion("incidentcompanion");
2978 sp<android::IBinder> ics(
2979 defaultServiceManager()->checkService(incidentcompanion));
2980 android::String16 package(calling_package.c_str());
2981 if (ics != nullptr) {
2982 MYLOGD("Checking user consent via incidentcompanion service\n");
2983 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
2984 calling_uid, package, String16(), String16(),
2985 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
2986 } else {
2987 MYLOGD(
2988 "Unable to check user consent; incidentcompanion service unavailable\n");
2989 return RunStatus::USER_CONSENT_TIMED_OUT;
2990 }
2991 UserConsentResult consent_result = consent_callback_->getResult();
2992 int timeout_ms = 30 * 1000;
2993 while (consent_result == UserConsentResult::UNAVAILABLE &&
2994 consent_callback_->getElapsedTimeMs() < timeout_ms) {
2995 sleep(1);
2996 consent_result = consent_callback_->getResult();
2997 }
2998 if (consent_result == UserConsentResult::DENIED) {
2999 return RunStatus::USER_CONSENT_DENIED;
3000 }
3001 if (consent_result == UserConsentResult::UNAVAILABLE) {
3002 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3003 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3004 consent_callback_.get());
3005 return RunStatus::USER_CONSENT_TIMED_OUT;
3006 }
3007
3008 bool copy_succeeded =
3009 android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
3010 if (copy_succeeded) {
3011 android::os::UnlinkAndLogOnError(path_);
3012 }
3013 return copy_succeeded ? Dumpstate::RunStatus::OK
3014 : Dumpstate::RunStatus::ERROR;
3015}
3016
3017void Dumpstate::HandleRunStatus(Dumpstate::RunStatus status) {
3018 if (listener_ != nullptr) {
Nandana Duttbabf6c72019-01-15 14:11:12 +00003019 switch (status) {
3020 case Dumpstate::RunStatus::OK:
Gavin Corkerya44686c2022-11-23 18:16:51 +00003021 listener_->onFinished(path_.c_str());
Nandana Duttbabf6c72019-01-15 14:11:12 +00003022 break;
3023 case Dumpstate::RunStatus::HELP:
3024 break;
3025 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003026 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00003027 break;
3028 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003029 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
3030 break;
3031 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3032 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
3033 break;
3034 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
3035 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00003036 break;
3037 }
3038 }
Nandana Duttbabf6c72019-01-15 14:11:12 +00003039}
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003040void Dumpstate::Cancel() {
3041 CleanupTmpFiles();
3042 android::os::UnlinkAndLogOnError(log_path_);
3043 for (int i = 0; i < NUM_OF_DUMPS; i++) {
3044 android::os::UnlinkAndLogOnError(ds.bugreport_internal_dir_ + "/" +
3045 kDumpstateBoardFiles[i]);
3046 }
3047 tombstone_data_.clear();
3048 anr_data_.clear();
Woody Lin20767a92022-11-29 15:50:24 +08003049 shutdown_checkpoints_.clear();
Rhed Jao0daac912020-08-21 14:48:20 +08003050
3051 // Instead of shutdown the pool, we delete temporary files directly since
3052 // shutdown blocking the call.
3053 if (dump_pool_) {
3054 dump_pool_->deleteTempFiles();
3055 }
3056 if (zip_entry_tasks_) {
3057 zip_entry_tasks_->run(/*do_cancel =*/ true);
3058 }
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003059}
3060
Kean Mariotti306633e2022-09-05 16:30:47 +00003061void Dumpstate::PreDumpUiData() {
3062 MaybeSnapshotUiTraces();
3063}
3064
Nandana Dutt979388e2018-11-30 16:48:55 +00003065/*
3066 * Dumps relevant information to a bugreport based on the given options.
3067 *
3068 * The bugreport can be dumped to a file or streamed to a socket.
3069 *
3070 * How dumping to file works:
3071 * stdout is redirected to a temporary file. This will later become the main bugreport entry.
3072 * stderr is redirected a log file.
3073 *
3074 * The temporary bugreport is then populated via printfs, dumping contents of files and
3075 * output of commands to stdout.
3076 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003077 * A bunch of other files and dumps are added to the zip archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00003078 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003079 * The temporary bugreport file and the log file also get added to the archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00003080 *
mhasank2d75c442020-06-11 15:05:25 -07003081 * Bugreports are first generated in a local directory and later copied to the caller's fd
3082 * or directory if supplied.
Nandana Dutt979388e2018-11-30 16:48:55 +00003083 */
Nandana Duttd2f5f082019-01-18 17:13:52 +00003084Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
3085 const std::string& calling_package) {
Rhed Jao5377d792020-07-16 17:37:39 +08003086 DurationReporter duration_reporter("RUN INTERNAL", /* logcat_only = */true);
Nandana Dutt979388e2018-11-30 16:48:55 +00003087 LogDumpOptions(*options_);
Nandana Dutt197661d2018-11-16 16:40:21 +00003088 if (!options_->ValidateOptions()) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00003089 MYLOGE("Invalid options specified\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003090 return RunStatus::INVALID_INPUT;
3091 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003092 /* set as high priority, and protect from OOM killer */
3093 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003094
Felipe Lemed071c682016-10-20 16:48:00 -07003095 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07003096 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003097 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003098 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003099 } else {
3100 /* fallback to kernels <= 2.6.35 */
3101 oom_adj = fopen("/proc/self/oom_adj", "we");
3102 if (oom_adj) {
3103 fputs("-17", oom_adj);
3104 fclose(oom_adj);
3105 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003106 }
3107
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003108 if (version_ == VERSION_DEFAULT) {
3109 version_ = VERSION_CURRENT;
Michal Karpinski4db754f2015-12-11 18:04:32 +00003110 }
3111
Chris Morin5a50d482022-02-01 17:41:18 -08003112 if (version_ != VERSION_CURRENT) {
3113 MYLOGE("invalid version requested ('%s'); supported values are: ('%s', '%s')\n",
3114 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003115 return RunStatus::INVALID_INPUT;
Felipe Lemed071c682016-10-20 16:48:00 -07003116 }
3117
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003118 if (options_->show_header_only) {
3119 PrintHeader();
3120 return RunStatus::OK;
Felipe Lemed071c682016-10-20 16:48:00 -07003121 }
3122
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003123 MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n",
3124 calling_uid, calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003125
Felipe Leme7447d7c2016-11-03 18:12:22 -07003126 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003127 std::string stats_path =
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003128 android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003129 progress_.reset(new Progress(stats_path));
Felipe Leme7447d7c2016-11-03 18:12:22 -07003130
Sahana Raof35ed432019-07-12 10:47:52 +01003131 if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
3132 MYLOGE("Failed to acquire wake lock: %s\n", strerror(errno));
3133 } else {
3134 // Wake lock will be released automatically on process death
3135 MYLOGD("Wake lock acquired.\n");
3136 }
3137
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08003138 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07003139
Felipe Lemef0292972016-11-22 13:57:05 -08003140 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07003141 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
3142 }
3143
Kevin Jeonfa64e642023-07-27 11:36:41 -04003144 if (PropertiesHelper::IsStrictRun()) {
3145 MYLOGI(
3146 "Running on strict-run mode, which has shorter timeouts "
3147 "(to disable, call 'setprop dumpstate.strict_run false')\n");
3148 }
3149
Nandana Dutt235c6672019-11-14 15:22:32 +00003150 MYLOGI("dumpstate info: id=%d, args='%s', bugreport_mode= %s bugreport format version: %s\n",
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00003151 id_, options_->args.c_str(), options_->bugreport_mode_string.c_str(), version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08003152
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003153 do_early_screenshot_ = options_->do_progress_updates;
Felipe Lemee338bf62015-12-07 14:03:50 -08003154
Christopher Ferrised9354f2014-10-01 17:35:01 -07003155 // If we are going to use a socket, do it as early as possible
3156 // to avoid timeouts from bugreport.
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003157 if (options_->stream_to_socket || options_->progress_updates_to_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07003158 MYLOGD("Opening control socket\n");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003159 control_socket_fd_ = open_socket_fn_("dumpstate");
Nandana Dutta344cb62019-02-22 15:12:35 +00003160 if (control_socket_fd_ == -1) {
3161 return ERROR;
3162 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003163 if (options_->progress_updates_to_socket) {
3164 options_->do_progress_updates = 1;
3165 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07003166 }
3167
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003168 if (!PrepareToWriteToFile()) {
3169 return ERROR;
3170 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08003171
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003172 // Interactive, wear & telephony modes are default to true.
3173 // and may enable from cli option or when using control socket
3174 if (options_->do_progress_updates) {
3175 // clang-format off
3176 std::vector<std::string> am_args = {
3177 "--receiver-permission", "android.permission.DUMP",
3178 };
3179 // clang-format on
3180 // Send STARTED broadcast for apps that listen to bugreport generation events
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003181 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED",
3182 am_args, multiuser_get_user_id(calling_uid));
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003183 if (options_->progress_updates_to_socket) {
3184 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08003185 }
3186 }
3187
Nick Kralevichf3599b32016-01-25 15:05:16 -08003188 /* read /proc/cmdline before dropping root */
3189 FILE *cmdline = fopen("/proc/cmdline", "re");
3190 if (cmdline) {
3191 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
3192 fclose(cmdline);
3193 }
3194
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003195 if (options_->do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08003196 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05003197 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003198
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003199 if (zip_file != nullptr) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003200 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
3201 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003202 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08003203 }
3204 }
3205
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003206 int dup_stdout_fd;
3207 int dup_stderr_fd;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003208 // Redirect stderr to log_path_ for debugging.
3209 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
3210 if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
3211 return ERROR;
3212 }
3213 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
3214 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
3215 strerror(errno));
3216 }
Nandana Dutt979388e2018-11-30 16:48:55 +00003217
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003218 // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
3219 // moved into zip file later, if zipping.
3220 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
3221 // TODO: why not write to a file instead of stdout to overcome this problem?
3222 /* TODO: rather than generating a text file now and zipping it later,
3223 it would be more efficient to redirect stdout to the zip entry
3224 directly, but the libziparchive doesn't support that option yet. */
3225 if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
3226 return ERROR;
3227 }
3228 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
3229 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
3230 tmp_path_.c_str(), strerror(errno));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003231 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08003232
3233 // Don't buffer stdout
3234 setvbuf(stdout, nullptr, _IONBF, 0);
3235
Rhed Jao5377d792020-07-16 17:37:39 +08003236 // Enable the parallel run if the client requests to output to a file.
3237 EnableParallelRunIfNeeded();
3238 // Using scope guard to make sure the dump pool can be shut down correctly.
3239 auto scope_guard_to_shutdown_pool = android::base::make_scope_guard([=]() {
3240 ShutdownDumpPool();
3241 });
3242
Felipe Leme608385d2016-02-01 10:35:38 -08003243 // NOTE: there should be no stdout output until now, otherwise it would break the header.
3244 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08003245 // duration is logged into MYLOG instead.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003246 PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003247
Gavin Corkery6968f552020-11-22 18:09:05 +00003248 bool is_dumpstate_restricted = options_->telephony_only
3249 || options_->wifi_only
3250 || options_->limited_only;
3251 if (!is_dumpstate_restricted) {
Paul Chang0d2aad72020-02-13 20:04:03 +08003252 // Invoke critical dumpsys first to preserve system state, before doing anything else.
Jichao Lie89d9c12019-11-21 19:02:51 -08003253 RunDumpsysCritical();
Gavin Corkery6968f552020-11-22 18:09:05 +00003254 }
3255 MaybeTakeEarlyScreenshot();
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003256
3257 if (!is_dumpstate_restricted) {
3258 // Snapshot the system trace now (if running) to avoid that dumpstate's
3259 // own activity pushes out interesting data from the trace ring buffer.
3260 // The trace file is added to the zip by MaybeAddSystemTraceToZip().
3261 MaybeSnapshotSystemTrace();
Yohei Yukawa95305b32021-03-09 07:54:27 -08003262
Kean Mariotti306633e2022-09-05 16:30:47 +00003263 // Snapshot the UI traces now (if running).
3264 // The trace files will be added to bugreport later.
3265 MaybeSnapshotUiTraces();
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003266 }
Gavin Corkery6968f552020-11-22 18:09:05 +00003267 onUiIntensiveBugreportDumpsFinished(calling_uid);
3268 MaybeCheckUserConsent(calling_uid, calling_package);
3269 if (options_->telephony_only) {
3270 DumpstateTelephonyOnly(calling_package);
3271 } else if (options_->wifi_only) {
3272 DumpstateWifiOnly();
3273 } else if (options_->limited_only) {
3274 DumpstateLimitedOnly();
3275 } else {
Nandana Dutt4be45d12018-09-26 15:04:23 +01003276 // Dump state for the default case. This also drops root.
Jichao Lie89d9c12019-11-21 19:02:51 -08003277 RunStatus s = DumpstateDefaultAfterCritical();
Nandana Dutt5c390032019-03-12 10:52:56 +00003278 if (s != RunStatus::OK) {
Nandana Duttaac6f582019-07-26 14:32:47 +01003279 if (s == RunStatus::USER_CONSENT_DENIED) {
Nandana Dutt5c390032019-03-12 10:52:56 +00003280 HandleUserConsentDenied();
3281 }
3282 return s;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08003283 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07003284 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07003285
Felipe Leme55b42a62015-11-10 17:39:08 -08003286 /* close output if needed */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003287 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003288
Abhijeet Kaure370d682019-10-01 16:49:30 +01003289 // Zip the (now complete) .tmp file within the internal directory.
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003290 ATRACE_BEGIN("FinalizeFile");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003291 FinalizeFile();
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003292 ATRACE_END();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003293
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003294 // Share the final file with the caller if the user has consented or Shell is the caller.
Nandana Duttd2f5f082019-01-18 17:13:52 +00003295 Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
Gavin Corkerya44686c2022-11-23 18:16:51 +00003296 if (CalledByApi() && !options_->is_consent_deferred) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003297 status = CopyBugreportIfUserConsented(calling_uid);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003298 if (status != Dumpstate::RunStatus::OK &&
3299 status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3300 // Do an early return if there were errors. We make an exception for consent
3301 // timing out because it's possible the user got distracted. In this case the
3302 // bugreport is not shared but made available for manual retrieval.
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003303 MYLOGI("User denied consent. Returning\n");
Nandana Duttd2f5f082019-01-18 17:13:52 +00003304 return status;
3305 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003306 if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3307 MYLOGI(
3308 "Did not receive user consent yet."
3309 " Will not copy the bugreport artifacts to caller.\n");
Abhijeet Kaur57627412019-04-17 16:00:09 +01003310 const String16 incidentcompanion("incidentcompanion");
3311 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
3312 if (ics != nullptr) {
3313 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3314 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3315 consent_callback_.get());
3316 } else {
3317 MYLOGD("Unable to cancel user consent; incidentcompanion service unavailable\n");
3318 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003319 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003320 }
3321
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003322 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003323 if (options_->do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09003324 for (int i = 0; i < 3; i++) {
3325 Vibrate(75);
3326 usleep((75 + 50) * 1000);
3327 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003328 }
3329
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003330 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
3331 progress_->GetInitialMax());
3332 progress_->Save();
3333 MYLOGI("done (id %d)\n", id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003334
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003335 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08003336
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003337 if (control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07003338 MYLOGD("Closing control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003339 close(control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07003340 }
3341
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003342 tombstone_data_.clear();
3343 anr_data_.clear();
Woody Lin20767a92022-11-29 15:50:24 +08003344 shutdown_checkpoints_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01003345
Nandana Duttd2f5f082019-01-18 17:13:52 +00003346 return (consent_callback_ != nullptr &&
3347 consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
3348 ? USER_CONSENT_TIMED_OUT
3349 : RunStatus::OK;
3350}
3351
Paul Chang0d2aad72020-02-13 20:04:03 +08003352void Dumpstate::MaybeTakeEarlyScreenshot() {
3353 if (!options_->do_screenshot || !do_early_screenshot_) {
3354 return;
3355 }
3356
3357 TakeScreenshot();
3358}
3359
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003360void Dumpstate::MaybeSnapshotSystemTrace() {
3361 // If a background system trace is happening and is marked as "suitable for
3362 // bugreport" (i.e. bugreport_score > 0 in the trace config), this command
3363 // will stop it and serialize into SYSTEM_TRACE_SNAPSHOT. In the (likely)
3364 // case that no trace is ongoing, this command is a no-op.
3365 // Note: this should not be enqueued as we need to freeze the trace before
3366 // dumpstate starts. Otherwise the trace ring buffers will contain mostly
3367 // the dumpstate's own activity which is irrelevant.
3368 int res = RunCommand(
3369 "SERIALIZE PERFETTO TRACE",
3370 {"perfetto", "--save-for-bugreport"},
3371 CommandOptions::WithTimeout(10)
3372 .DropRoot()
3373 .CloseAllFileDescriptorsOnExec()
3374 .Build());
3375 has_system_trace_ = res == 0;
3376 // MaybeAddSystemTraceToZip() will take care of copying the trace in the zip
3377 // file in the later stages.
3378}
3379
Kean Mariotti306633e2022-09-05 16:30:47 +00003380void Dumpstate::MaybeSnapshotUiTraces() {
3381 if (PropertiesHelper::IsUserBuild() || options_->use_predumped_ui_data) {
3382 return;
3383 }
Hongwei Wang9ec5c252023-01-24 15:09:59 -08003384
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003385 const std::vector<std::vector<std::string>> dumpTracesForBugReportCommands = {
3386 {"dumpsys", "activity", "service", "SystemUIService", "WMShell", "protolog",
3387 "save-for-bugreport"},
3388 {"dumpsys", "activity", "service", "SystemUIService", "WMShell", "transitions", "tracing",
3389 "save-for-bugreport"},
3390 {"cmd", "input_method", "tracing", "save-for-bugreport"},
3391 {"cmd", "window", "tracing", "save-for-bugreport"},
3392 {"cmd", "window", "shell", "tracing", "save-for-bugreport"},
3393 };
Hongwei Wang39229132023-01-24 15:09:59 -08003394
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003395 for (const auto& command : dumpTracesForBugReportCommands) {
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003396 RunCommand(
3397 // Empty name because it's not intended to be classified as a bugreport section.
3398 // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003399 "", command,
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003400 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
3401 }
Kean Mariotti306633e2022-09-05 16:30:47 +00003402
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003403 // This command needs to be run as root
Kean Mariotti306633e2022-09-05 16:30:47 +00003404 static const auto SURFACEFLINGER_COMMAND_SAVE_ALL_TRACES = std::vector<std::string> {
3405 "service", "call", "SurfaceFlinger", "1042"
3406 };
3407 // Empty name because it's not intended to be classified as a bugreport section.
3408 // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
3409 RunCommand(
3410 "", SURFACEFLINGER_COMMAND_SAVE_ALL_TRACES,
3411 CommandOptions::WithTimeout(10).Always().AsRoot().RedirectStderr().Build());
3412}
3413
3414void Dumpstate::MaybePostProcessUiTraces() {
3415 if (PropertiesHelper::IsUserBuild()) {
3416 return;
3417 }
3418
3419 RunCommand(
3420 // Empty name because it's not intended to be classified as a bugreport section.
3421 // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
3422 "", {
3423 "/system/xbin/su", "system",
3424 "/system/bin/layertracegenerator",
3425 "/data/misc/wmtrace/transactions_trace.winscope",
3426 "/data/misc/wmtrace/layers_trace_from_transactions.winscope"
3427 },
3428 CommandOptions::WithTimeout(120).Always().RedirectStderr().Build());
3429}
3430
3431void Dumpstate::MaybeAddUiTracesToZip() {
3432 if (PropertiesHelper::IsUserBuild()) {
3433 return;
3434 }
3435
3436 ds.AddDir(WMTRACE_DATA_DIR, false);
Yohei Yukawa95305b32021-03-09 07:54:27 -08003437}
3438
Paul Changeb4b4642020-05-28 22:05:47 +08003439void Dumpstate::onUiIntensiveBugreportDumpsFinished(int32_t calling_uid) {
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003440 if (multiuser_get_app_id(calling_uid) == AID_SHELL || !CalledByApi()) {
Paul Changc490e662020-04-11 18:14:09 +08003441 return;
3442 }
3443 if (listener_ != nullptr) {
3444 // Let listener know ui intensive bugreport dumps are finished, then it can do event
3445 // handling if required.
Paul Changeb4b4642020-05-28 22:05:47 +08003446 listener_->onUiIntensiveBugreportDumpsFinished();
Paul Changc490e662020-04-11 18:14:09 +08003447 }
3448}
3449
Jichao Lie89d9c12019-11-21 19:02:51 -08003450void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) {
Gavin Corkerya44686c2022-11-23 18:16:51 +00003451 if (multiuser_get_app_id(calling_uid) == AID_SHELL ||
3452 !CalledByApi() || options_->is_consent_deferred) {
3453 // No need to get consent for shell triggered dumpstates, or not
3454 // through bugreporting API (i.e. no fd to copy back), or when consent
3455 // is deferred.
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003456 return;
3457 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003458 consent_callback_ = new ConsentCallback();
3459 const String16 incidentcompanion("incidentcompanion");
3460 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
Jichao Lie89d9c12019-11-21 19:02:51 -08003461 android::String16 package(calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003462 if (ics != nullptr) {
3463 MYLOGD("Checking user consent via incidentcompanion service\n");
Steven Leeb573eb82022-11-29 22:31:35 +08003464 int flags = 0x1; // IncidentManager.FLAG_CONFIRMATION_DIALOG
3465 if (IsConsentlessBugreportAllowed(*options_)) {
3466 flags |= 0x2; // IncidentManager.FLAG_ALLOW_CONSENTLESS_BUGREPORT
3467 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003468 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
Steven Leeb573eb82022-11-29 22:31:35 +08003469 calling_uid, package, String16(), String16(), flags, consent_callback_.get());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003470 } else {
3471 MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
3472 }
3473}
3474
Nandana Dutt5c390032019-03-12 10:52:56 +00003475bool Dumpstate::IsUserConsentDenied() const {
3476 return ds.consent_callback_ != nullptr &&
3477 ds.consent_callback_->getResult() == UserConsentResult::DENIED;
3478}
3479
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01003480bool Dumpstate::CalledByApi() const {
3481 return ds.options_->bugreport_fd.get() != -1 ? true : false;
3482}
3483
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003484void Dumpstate::CleanupTmpFiles() {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003485 android::os::UnlinkAndLogOnError(tmp_path_);
3486 android::os::UnlinkAndLogOnError(screenshot_path_);
3487 android::os::UnlinkAndLogOnError(path_);
Gavin Corkery789d7a52021-02-24 23:52:35 +00003488 if (dump_traces_path != nullptr) {
3489 android::os::UnlinkAndLogOnError(dump_traces_path);
3490 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003491}
3492
Rhed Jao5377d792020-07-16 17:37:39 +08003493void Dumpstate::EnableParallelRunIfNeeded() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003494 if (!PropertiesHelper::IsParallelRun()) {
Rhed Jao5377d792020-07-16 17:37:39 +08003495 return;
3496 }
3497 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003498 zip_entry_tasks_ = std::make_unique<TaskQueue>();
Rhed Jao5377d792020-07-16 17:37:39 +08003499}
3500
3501void Dumpstate::ShutdownDumpPool() {
3502 if (dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08003503 dump_pool_.reset();
Rhed Jao5377d792020-07-16 17:37:39 +08003504 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003505 if (zip_entry_tasks_) {
3506 zip_entry_tasks_->run(/* do_cancel = */true);
3507 zip_entry_tasks_ = nullptr;
3508 }
3509}
3510
3511void Dumpstate::EnqueueAddZipEntryAndCleanupIfNeeded(const std::string& entry_name,
3512 const std::string& entry_path) {
3513 auto func_add_zip_entry_and_cleanup = [=](bool task_cancelled) {
3514 if (!task_cancelled) {
3515 AddZipEntry(entry_name, entry_path);
3516 }
3517 android::os::UnlinkAndLogOnError(entry_path);
3518 };
3519 if (zip_entry_tasks_) {
3520 // Enqueues AddZipEntryAndCleanup function if the parallel run is enabled.
3521 zip_entry_tasks_->add(func_add_zip_entry_and_cleanup, _1);
3522 } else {
3523 // Invokes AddZipEntryAndCleanup immediately
3524 std::invoke(func_add_zip_entry_and_cleanup, /* task_cancelled = */false);
3525 }
Rhed Jao5377d792020-07-16 17:37:39 +08003526}
3527
Nandana Duttd2f5f082019-01-18 17:13:52 +00003528Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
3529 MYLOGD("User denied consent; deleting files and returning\n");
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003530 CleanupTmpFiles();
Nandana Duttd2f5f082019-01-18 17:13:52 +00003531 return USER_CONSENT_DENIED;
3532}
3533
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003534Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented(int32_t calling_uid) {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003535 // If the caller has asked to copy the bugreport over to their directory, we need explicit
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003536 // user consent (unless the caller is Shell).
3537 UserConsentResult consent_result;
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003538 if (multiuser_get_app_id(calling_uid) == AID_SHELL) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003539 consent_result = UserConsentResult::APPROVED;
3540 } else {
3541 consent_result = consent_callback_->getResult();
3542 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003543 if (consent_result == UserConsentResult::UNAVAILABLE) {
3544 // User has not responded yet.
3545 uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
Hunter Knepshield70610fa2020-01-03 15:27:33 -08003546 // Telephony is a fast report type, particularly on user builds where information may be
3547 // more aggressively limited. To give the user time to read the consent dialog, increase the
3548 // timeout.
3549 uint64_t timeout_ms = options_->telephony_only ? TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS
3550 : USER_CONSENT_TIMEOUT_MS;
3551 if (elapsed_ms < timeout_ms) {
3552 uint delay_seconds = (timeout_ms - elapsed_ms) / 1000;
Nandana Duttd2f5f082019-01-18 17:13:52 +00003553 MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
3554 sleep(delay_seconds);
3555 }
3556 consent_result = consent_callback_->getResult();
3557 }
3558 if (consent_result == UserConsentResult::DENIED) {
3559 // User has explicitly denied sharing with the app. To be safe delete the
3560 // internal bugreport & tmp files.
3561 return HandleUserConsentDenied();
3562 }
3563 if (consent_result == UserConsentResult::APPROVED) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00003564 bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
3565 if (copy_succeeded) {
3566 android::os::UnlinkAndLogOnError(path_);
Abhijeet Kaur9ce94672020-04-01 17:22:36 +01003567 if (options_->do_screenshot &&
3568 options_->screenshot_fd.get() != -1 &&
3569 !options_->is_screenshot_copied) {
3570 copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
3571 options_->screenshot_fd.get());
3572 options_->is_screenshot_copied = copy_succeeded;
3573 if (copy_succeeded) {
3574 android::os::UnlinkAndLogOnError(screenshot_path_);
3575 }
3576 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003577 }
3578 return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
3579 } else if (consent_result == UserConsentResult::UNAVAILABLE) {
3580 // consent_result is still UNAVAILABLE. The user has likely not responded yet.
3581 // Since we do not have user consent to share the bugreport it does not get
3582 // copied over to the calling app but remains in the internal directory from
3583 // where the user can manually pull it.
Paul Changce644212021-05-11 16:06:45 +08003584 std::string final_path = GetPath(".zip");
3585 bool copy_succeeded = android::os::CopyFileToFile(path_, final_path);
3586 if (copy_succeeded) {
3587 android::os::UnlinkAndLogOnError(path_);
3588 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003589 return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
3590 }
3591 // Unknown result; must be a programming error.
3592 MYLOGE("Unknown user consent result:%d\n", consent_result);
3593 return Dumpstate::RunStatus::ERROR;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003594}
3595
Nandana Duttf02564e2019-02-15 15:24:24 +00003596Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003597 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
3598 Dumpstate::RunStatus status = options->Initialize(argc, argv);
3599 if (status == Dumpstate::RunStatus::OK) {
Nandana Duttf02564e2019-02-15 15:24:24 +00003600 SetOptions(std::move(options));
Nandana Duttd2f5f082019-01-18 17:13:52 +00003601 // When directly running dumpstate binary, the output is not expected to be written
3602 // to any external file descriptor.
Nandana Duttf02564e2019-02-15 15:24:24 +00003603 assert(options_->bugreport_fd.get() == -1);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003604
3605 // calling_uid and calling_package are for user consent to share the bugreport with
Abhijeet Kaura407fb82020-03-27 12:51:12 +00003606 // an app; they are irrelevant here because bugreport is triggered via command line.
3607 // Update Last ID before calling Run().
3608 Initialize();
Nikhil Kumarb70622a2023-06-15 15:37:19 +01003609 status = Run(0 /* calling_uid */, "" /* calling_package */);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003610 }
Nandana Duttf02564e2019-02-15 15:24:24 +00003611 return status;
3612}
3613
3614/* Main entry point for dumpstate binary. */
3615int run_main(int argc, char* argv[]) {
3616 Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003617
3618 switch (status) {
3619 case Dumpstate::RunStatus::OK:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003620 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003621 case Dumpstate::RunStatus::HELP:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003622 ShowUsage();
3623 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003624 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003625 fprintf(stderr, "Invalid combination of args\n");
3626 ShowUsage();
3627 exit(1);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003628 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003629 FALLTHROUGH_INTENDED;
3630 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3631 FALLTHROUGH_INTENDED;
3632 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003633 exit(2);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003634 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003635}
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003636
3637// TODO(111441001): Default DumpOptions to sensible values.
3638Dumpstate::Dumpstate(const std::string& version)
3639 : pid_(getpid()),
3640 options_(new Dumpstate::DumpOptions()),
Nandana Dutt402a8392019-06-14 14:25:13 +01003641 last_reported_percent_progress_(0),
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003642 version_(version),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003643 now_(time(nullptr)),
3644 open_socket_fn_(open_socket) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003645}
3646
3647Dumpstate& Dumpstate::GetInstance() {
3648 static Dumpstate singleton_(android::base::GetProperty("dumpstate.version", VERSION_CURRENT));
3649 return singleton_;
3650}
3651
Rhed Jao5377d792020-07-16 17:37:39 +08003652DurationReporter::DurationReporter(const std::string& title, bool logcat_only, bool verbose,
3653 int duration_fd) : title_(title), logcat_only_(logcat_only), verbose_(verbose),
3654 duration_fd_(duration_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003655 if (!title_.empty()) {
3656 started_ = Nanotime();
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003657 if (title_.find("SHOW MAP") == std::string::npos) {
3658 ATRACE_ASYNC_BEGIN(title_.c_str(), 0);
3659 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003660 }
3661}
3662
3663DurationReporter::~DurationReporter() {
3664 if (!title_.empty()) {
3665 float elapsed = (float)(Nanotime() - started_) / NANOS_PER_SEC;
chenqiwuaf8b2d92019-12-12 18:53:51 +08003666 if (elapsed >= .5f || verbose_) {
3667 MYLOGD("Duration of '%s': %.2fs\n", title_.c_str(), elapsed);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003668 }
chenqiwuaf8b2d92019-12-12 18:53:51 +08003669 if (!logcat_only_) {
3670 // Use "Yoda grammar" to make it easier to grep|sort sections.
Rhed Jao5377d792020-07-16 17:37:39 +08003671 dprintf(duration_fd_, "------ %.3fs was the duration of '%s' ------\n",
3672 elapsed, title_.c_str());
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003673 }
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003674 if (title_.find("SHOW MAP") == std::string::npos) {
3675 ATRACE_ASYNC_END(title_.c_str(), 0);
3676 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003677 }
3678}
3679
3680const int32_t Progress::kDefaultMax = 5000;
3681
3682Progress::Progress(const std::string& path) : Progress(Progress::kDefaultMax, 1.1, path) {
3683}
3684
3685Progress::Progress(int32_t initial_max, int32_t progress, float growth_factor)
3686 : Progress(initial_max, growth_factor, "") {
3687 progress_ = progress;
3688}
3689
3690Progress::Progress(int32_t initial_max, float growth_factor, const std::string& path)
3691 : initial_max_(initial_max),
3692 progress_(0),
3693 max_(initial_max),
3694 growth_factor_(growth_factor),
3695 n_runs_(0),
3696 average_max_(0),
3697 path_(path) {
3698 if (!path_.empty()) {
3699 Load();
3700 }
3701}
3702
3703void Progress::Load() {
3704 MYLOGD("Loading stats from %s\n", path_.c_str());
3705 std::string content;
3706 if (!android::base::ReadFileToString(path_, &content)) {
3707 MYLOGI("Could not read stats from %s; using max of %d\n", path_.c_str(), max_);
3708 return;
3709 }
3710 if (content.empty()) {
3711 MYLOGE("No stats (empty file) on %s; using max of %d\n", path_.c_str(), max_);
3712 return;
3713 }
3714 std::vector<std::string> lines = android::base::Split(content, "\n");
3715
3716 if (lines.size() < 1) {
3717 MYLOGE("Invalid stats on file %s: not enough lines (%d). Using max of %d\n", path_.c_str(),
3718 (int)lines.size(), max_);
3719 return;
3720 }
3721 char* ptr;
3722 n_runs_ = strtol(lines[0].c_str(), &ptr, 10);
3723 average_max_ = strtol(ptr, nullptr, 10);
3724 if (n_runs_ <= 0 || average_max_ <= 0 || n_runs_ > STATS_MAX_N_RUNS ||
3725 average_max_ > STATS_MAX_AVERAGE) {
3726 MYLOGE("Invalid stats line on file %s: %s\n", path_.c_str(), lines[0].c_str());
3727 initial_max_ = Progress::kDefaultMax;
3728 } else {
3729 initial_max_ = average_max_;
3730 }
3731 max_ = initial_max_;
3732
3733 MYLOGI("Average max progress: %d in %d runs; estimated max: %d\n", average_max_, n_runs_, max_);
3734}
3735
3736void Progress::Save() {
3737 int32_t total = n_runs_ * average_max_ + progress_;
3738 int32_t runs = n_runs_ + 1;
3739 int32_t average = floor(((float)total) / runs);
3740 MYLOGI("Saving stats (total=%d, runs=%d, average=%d) on %s\n", total, runs, average,
3741 path_.c_str());
3742 if (path_.empty()) {
3743 return;
3744 }
3745
3746 std::string content = android::base::StringPrintf("%d %d\n", runs, average);
3747 if (!android::base::WriteStringToFile(content, path_)) {
3748 MYLOGE("Could not save stats on %s\n", path_.c_str());
3749 }
3750}
3751
3752int32_t Progress::Get() const {
3753 return progress_;
3754}
3755
3756bool Progress::Inc(int32_t delta_sec) {
3757 bool changed = false;
3758 if (delta_sec >= 0) {
3759 progress_ += delta_sec;
3760 if (progress_ > max_) {
3761 int32_t old_max = max_;
3762 max_ = floor((float)progress_ * growth_factor_);
3763 MYLOGD("Adjusting max progress from %d to %d\n", old_max, max_);
3764 changed = true;
3765 }
3766 }
3767 return changed;
3768}
3769
3770int32_t Progress::GetMax() const {
3771 return max_;
3772}
3773
3774int32_t Progress::GetInitialMax() const {
3775 return initial_max_;
3776}
3777
3778void Progress::Dump(int fd, const std::string& prefix) const {
3779 const char* pr = prefix.c_str();
3780 dprintf(fd, "%sprogress: %d\n", pr, progress_);
3781 dprintf(fd, "%smax: %d\n", pr, max_);
3782 dprintf(fd, "%sinitial_max: %d\n", pr, initial_max_);
3783 dprintf(fd, "%sgrowth_factor: %0.2f\n", pr, growth_factor_);
3784 dprintf(fd, "%spath: %s\n", pr, path_.c_str());
3785 dprintf(fd, "%sn_runs: %d\n", pr, n_runs_);
3786 dprintf(fd, "%saverage_max: %d\n", pr, average_max_);
3787}
3788
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003789std::string Dumpstate::GetPath(const std::string& suffix) const {
3790 return GetPath(bugreport_internal_dir_, suffix);
3791}
3792
3793std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
3794 return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
3795 name_.c_str(), suffix.c_str());
3796}
3797
3798void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
3799 progress_ = std::move(progress);
3800}
3801
3802void for_each_userid(void (*func)(int), const char *header) {
3803 std::string title = header == nullptr ? "for_each_userid" : android::base::StringPrintf(
3804 "for_each_userid(%s)", header);
3805 DurationReporter duration_reporter(title);
3806 if (PropertiesHelper::IsDryRun()) return;
3807
3808 DIR *d;
3809 struct dirent *de;
3810
3811 if (header) printf("\n------ %s ------\n", header);
3812 func(0);
3813
3814 if (!(d = opendir("/data/system/users"))) {
3815 printf("Failed to open /data/system/users (%s)\n", strerror(errno));
3816 return;
3817 }
3818
3819 while ((de = readdir(d))) {
3820 int userid;
3821 if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
3822 continue;
3823 }
3824 func(userid);
3825 }
3826
3827 closedir(d);
3828}
3829
3830static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
3831 DIR *d;
3832 struct dirent *de;
3833
3834 if (!(d = opendir("/proc"))) {
3835 printf("Failed to open /proc (%s)\n", strerror(errno));
3836 return;
3837 }
3838
3839 if (header) printf("\n------ %s ------\n", header);
3840 while ((de = readdir(d))) {
3841 if (ds.IsUserConsentDenied()) {
3842 MYLOGE(
3843 "Returning early because user denied consent to share bugreport with calling app.");
3844 closedir(d);
3845 return;
3846 }
3847 int pid;
3848 int fd;
3849 char cmdpath[255];
3850 char cmdline[255];
3851
3852 if (!(pid = atoi(de->d_name))) {
3853 continue;
3854 }
3855
3856 memset(cmdline, 0, sizeof(cmdline));
3857
3858 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
3859 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3860 TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
3861 close(fd);
3862 if (cmdline[0]) {
3863 helper(pid, cmdline, arg);
3864 continue;
3865 }
3866 }
3867
3868 // if no cmdline, a kernel thread has comm
3869 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
3870 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3871 TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
3872 close(fd);
3873 if (cmdline[1]) {
3874 cmdline[0] = '[';
3875 size_t len = strcspn(cmdline, "\f\b\r\n");
3876 cmdline[len] = ']';
3877 cmdline[len+1] = '\0';
3878 }
3879 }
3880 if (!cmdline[0]) {
3881 strcpy(cmdline, "N/A");
3882 }
3883 helper(pid, cmdline, arg);
3884 }
3885
3886 closedir(d);
3887}
3888
3889static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
3890 for_each_pid_func *func = (for_each_pid_func*) arg;
3891 func(pid, cmdline);
3892}
3893
3894void for_each_pid(for_each_pid_func func, const char *header) {
3895 std::string title = header == nullptr ? "for_each_pid"
3896 : android::base::StringPrintf("for_each_pid(%s)", header);
3897 DurationReporter duration_reporter(title);
3898 if (PropertiesHelper::IsDryRun()) return;
3899
3900 __for_each_pid(for_each_pid_helper, header, (void *) func);
3901}
3902
3903static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
3904 DIR *d;
3905 struct dirent *de;
3906 char taskpath[255];
3907 for_each_tid_func *func = (for_each_tid_func *) arg;
3908
3909 snprintf(taskpath, sizeof(taskpath), "/proc/%d/task", pid);
3910
3911 if (!(d = opendir(taskpath))) {
3912 printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
3913 return;
3914 }
3915
3916 func(pid, pid, cmdline);
3917
3918 while ((de = readdir(d))) {
3919 if (ds.IsUserConsentDenied()) {
3920 MYLOGE(
3921 "Returning early because user denied consent to share bugreport with calling app.");
3922 closedir(d);
3923 return;
3924 }
3925 int tid;
3926 int fd;
3927 char commpath[255];
3928 char comm[255];
3929
3930 if (!(tid = atoi(de->d_name))) {
3931 continue;
3932 }
3933
3934 if (tid == pid)
3935 continue;
3936
3937 snprintf(commpath, sizeof(commpath), "/proc/%d/comm", tid);
3938 memset(comm, 0, sizeof(comm));
3939 if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
3940 strcpy(comm, "N/A");
3941 } else {
3942 char *c;
3943 TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
3944 close(fd);
3945
3946 c = strrchr(comm, '\n');
3947 if (c) {
3948 *c = '\0';
3949 }
3950 }
3951 func(pid, tid, comm);
3952 }
3953
3954 closedir(d);
3955}
3956
3957void for_each_tid(for_each_tid_func func, const char *header) {
3958 std::string title = header == nullptr ? "for_each_tid"
3959 : android::base::StringPrintf("for_each_tid(%s)", header);
3960 DurationReporter duration_reporter(title);
3961
3962 if (PropertiesHelper::IsDryRun()) return;
3963
3964 __for_each_pid(for_each_tid_helper, header, (void *) func);
3965}
3966
3967void show_wchan(int pid, int tid, const char *name) {
3968 if (PropertiesHelper::IsDryRun()) return;
3969
3970 char path[255];
3971 char buffer[255];
3972 int fd, ret, save_errno;
3973 char name_buffer[255];
3974
3975 memset(buffer, 0, sizeof(buffer));
3976
3977 snprintf(path, sizeof(path), "/proc/%d/wchan", tid);
3978 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
3979 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
3980 return;
3981 }
3982
3983 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3984 save_errno = errno;
3985 close(fd);
3986
3987 if (ret < 0) {
3988 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
3989 return;
3990 }
3991
3992 snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
3993 pid == tid ? 0 : 3, "", name);
3994
3995 printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
3996
3997 return;
3998}
3999
4000// print time in centiseconds
4001static void snprcent(char *buffer, size_t len, size_t spc,
4002 unsigned long long time) {
4003 static long hz; // cache discovered hz
4004
4005 if (hz <= 0) {
4006 hz = sysconf(_SC_CLK_TCK);
4007 if (hz <= 0) {
4008 hz = 1000;
4009 }
4010 }
4011
4012 // convert to centiseconds
4013 time = (time * 100 + (hz / 2)) / hz;
4014
4015 char str[16];
4016
4017 snprintf(str, sizeof(str), " %llu.%02u",
4018 time / 100, (unsigned)(time % 100));
4019 size_t offset = strlen(buffer);
4020 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
4021 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
4022}
4023
4024// print permille as a percent
4025static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
4026 char str[16];
4027
4028 snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
4029 size_t offset = strlen(buffer);
4030 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
4031 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
4032}
4033
4034void show_showtime(int pid, const char *name) {
4035 if (PropertiesHelper::IsDryRun()) return;
4036
4037 char path[255];
4038 char buffer[1023];
4039 int fd, ret, save_errno;
4040
4041 memset(buffer, 0, sizeof(buffer));
4042
4043 snprintf(path, sizeof(path), "/proc/%d/stat", pid);
4044 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
4045 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
4046 return;
4047 }
4048
4049 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
4050 save_errno = errno;
4051 close(fd);
4052
4053 if (ret < 0) {
4054 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
4055 return;
4056 }
4057
4058 // field 14 is utime
4059 // field 15 is stime
4060 // field 42 is iotime
4061 unsigned long long utime = 0, stime = 0, iotime = 0;
4062 if (sscanf(buffer,
4063 "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
4064 "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
4065 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
4066 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
4067 &utime, &stime, &iotime) != 3) {
4068 return;
4069 }
4070
4071 unsigned long long total = utime + stime;
4072 if (!total) {
4073 return;
4074 }
4075
4076 unsigned permille = (iotime * 1000 + (total / 2)) / total;
4077 if (permille > 1000) {
4078 permille = 1000;
4079 }
4080
4081 // try to beautify and stabilize columns at <80 characters
4082 snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
4083 if ((name[0] != '[') || utime) {
4084 snprcent(buffer, sizeof(buffer), 57, utime);
4085 }
4086 snprcent(buffer, sizeof(buffer), 65, stime);
4087 if ((name[0] != '[') || iotime) {
4088 snprcent(buffer, sizeof(buffer), 73, iotime);
4089 }
4090 if (iotime) {
4091 snprdec(buffer, sizeof(buffer), 79, permille);
4092 }
4093 puts(buffer); // adds a trailing newline
4094
4095 return;
4096}
4097
4098void do_dmesg() {
4099 const char *title = "KERNEL LOG (dmesg)";
4100 DurationReporter duration_reporter(title);
4101 printf("------ %s ------\n", title);
4102
4103 if (PropertiesHelper::IsDryRun()) return;
4104
4105 /* Get size of kernel buffer */
4106 int size = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
4107 if (size <= 0) {
4108 printf("Unexpected klogctl return value: %d\n\n", size);
4109 return;
4110 }
4111 char *buf = (char *) malloc(size + 1);
4112 if (buf == nullptr) {
4113 printf("memory allocation failed\n\n");
4114 return;
4115 }
4116 int retval = klogctl(KLOG_READ_ALL, buf, size);
4117 if (retval < 0) {
4118 printf("klogctl failure\n\n");
4119 free(buf);
4120 return;
4121 }
4122 buf[retval] = '\0';
4123 printf("%s\n\n", buf);
4124 free(buf);
4125 return;
4126}
4127
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004128int Dumpstate::DumpFile(const std::string& title, const std::string& path) {
4129 DurationReporter duration_reporter(title);
4130
4131 int status = DumpFileToFd(STDOUT_FILENO, title, path);
4132
4133 UpdateProgress(WEIGHT_FILE);
4134
4135 return status;
4136}
4137
4138int read_file_as_long(const char *path, long int *output) {
4139 int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
4140 if (fd < 0) {
4141 int err = errno;
4142 MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
4143 return -1;
4144 }
4145 char buffer[50];
4146 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
4147 if (bytes_read == -1) {
4148 MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
4149 return -2;
4150 }
4151 if (bytes_read == 0) {
4152 MYLOGE("File %s is empty\n", path);
4153 return -3;
4154 }
4155 *output = atoi(buffer);
4156 return 0;
4157}
4158
4159/* calls skip to gate calling dump_from_fd recursively
4160 * in the specified directory. dump_from_fd defaults to
4161 * dump_file_from_fd above when set to NULL. skip defaults
4162 * to false when set to NULL. dump_from_fd will always be
4163 * called with title NULL.
4164 */
4165int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
4166 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4167 DurationReporter duration_reporter(title);
4168 DIR *dirp;
4169 struct dirent *d;
4170 char *newpath = nullptr;
4171 const char *slash = "/";
4172 int retval = 0;
4173
4174 if (!title.empty()) {
4175 printf("------ %s (%s) ------\n", title.c_str(), dir);
4176 }
4177 if (PropertiesHelper::IsDryRun()) return 0;
4178
4179 if (dir[strlen(dir) - 1] == '/') {
4180 ++slash;
4181 }
4182 dirp = opendir(dir);
4183 if (dirp == nullptr) {
4184 retval = -errno;
4185 MYLOGE("%s: %s\n", dir, strerror(errno));
4186 return retval;
4187 }
4188
4189 if (!dump_from_fd) {
4190 dump_from_fd = dump_file_from_fd;
4191 }
4192 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4193 if ((d->d_name[0] == '.')
4194 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4195 || (d->d_name[1] == '\0'))) {
4196 continue;
4197 }
4198 asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
4199 (d->d_type == DT_DIR) ? "/" : "");
4200 if (!newpath) {
4201 retval = -errno;
4202 continue;
4203 }
4204 if (skip && (*skip)(newpath)) {
4205 continue;
4206 }
4207 if (d->d_type == DT_DIR) {
4208 int ret = dump_files("", newpath, skip, dump_from_fd);
4209 if (ret < 0) {
4210 retval = ret;
4211 }
4212 continue;
4213 }
4214 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
4215 if (fd.get() < 0) {
4216 retval = -1;
4217 printf("*** %s: %s\n", newpath, strerror(errno));
4218 continue;
4219 }
4220 (*dump_from_fd)(nullptr, newpath, fd.get());
4221 }
4222 closedir(dirp);
4223 if (!title.empty()) {
4224 printf("\n");
4225 }
4226 return retval;
4227}
4228
4229/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
4230 * it's possible to avoid issues where opening the file itself can get
4231 * stuck.
4232 */
4233int dump_file_from_fd(const char *title, const char *path, int fd) {
4234 if (PropertiesHelper::IsDryRun()) return 0;
4235
4236 int flags = fcntl(fd, F_GETFL);
4237 if (flags == -1) {
4238 printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
4239 return -1;
4240 } else if (!(flags & O_NONBLOCK)) {
4241 printf("*** %s: fd must have O_NONBLOCK set.\n", path);
4242 return -1;
4243 }
4244 return DumpFileFromFdToFd(title, path, fd, STDOUT_FILENO, PropertiesHelper::IsDryRun());
4245}
4246
4247int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004248 const CommandOptions& options, bool verbose_duration, int out_fd) {
4249 DurationReporter duration_reporter(title, false /* logcat_only */,
4250 verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004251
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004252 int status = RunCommandToFd(out_fd, title, full_command, options);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004253
4254 /* TODO: for now we're simplifying the progress calculation by using the
4255 * timeout as the weight. It's a good approximation for most cases, except when calling dumpsys,
4256 * where its weight should be much higher proportionally to its timeout.
4257 * Ideally, it should use a options.EstimatedDuration() instead...*/
4258 UpdateProgress(options.Timeout());
4259
4260 return status;
4261}
4262
4263void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
Rhed Jaoe017f982020-07-21 17:58:41 +08004264 const CommandOptions& options, long dumpsysTimeoutMs, int out_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004265 long timeout_ms = dumpsysTimeoutMs > 0 ? dumpsysTimeoutMs : options.TimeoutInMs();
4266 std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-T", std::to_string(timeout_ms)};
4267 dumpsys.insert(dumpsys.end(), dumpsys_args.begin(), dumpsys_args.end());
Rhed Jaoe017f982020-07-21 17:58:41 +08004268 RunCommand(title, dumpsys, options, false, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004269}
4270
Dieter Hsu105ad0c2020-09-29 15:23:33 +08004271static int open_socket(const char* service) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004272 int s = android_get_control_socket(service);
4273 if (s < 0) {
4274 MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
4275 return -1;
4276 }
4277 fcntl(s, F_SETFD, FD_CLOEXEC);
4278
4279 // Set backlog to 0 to make sure that queue size will be minimum.
4280 // In Linux, because the minimum queue will be 1, connect() will be blocked
4281 // if the other clients already called connect() and the connection request was not accepted.
4282 if (listen(s, 0) < 0) {
4283 MYLOGE("listen(control socket): %s\n", strerror(errno));
4284 return -1;
4285 }
4286
4287 struct sockaddr addr;
4288 socklen_t alen = sizeof(addr);
Abhijeet Kaur2113cae2019-09-13 09:24:15 +01004289 int fd = accept4(s, &addr, &alen, SOCK_CLOEXEC);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004290
4291 // Close socket just after accept(), to make sure that connect() by client will get error
4292 // when the socket is used by the other services.
4293 // There is still a race condition possibility between accept and close, but there is no way
4294 // to close-on-accept atomically.
4295 // See detail; b/123306389#comment25
4296 close(s);
4297
4298 if (fd < 0) {
4299 MYLOGE("accept(control socket): %s\n", strerror(errno));
4300 return -1;
4301 }
4302
4303 return fd;
4304}
4305
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004306// TODO: should call is_valid_output_file and/or be merged into it.
4307void create_parent_dirs(const char *path) {
4308 char *chp = const_cast<char *> (path);
4309
4310 /* skip initial slash */
4311 if (chp[0] == '/')
4312 chp++;
4313
4314 /* create leading directories, if necessary */
4315 struct stat dir_stat;
4316 while (chp && chp[0]) {
4317 chp = strchr(chp, '/');
4318 if (chp) {
4319 *chp = 0;
4320 if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
4321 MYLOGI("Creating directory %s\n", path);
4322 if (mkdir(path, 0770)) { /* drwxrwx--- */
4323 MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
4324 } else if (chown(path, AID_SHELL, AID_SHELL)) {
4325 MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
4326 }
4327 }
4328 *chp++ = '/';
4329 }
4330 }
4331}
4332
4333bool _redirect_to_file(FILE* redirect, char* path, int truncate_flag) {
4334 create_parent_dirs(path);
4335
4336 int fd = TEMP_FAILURE_RETRY(open(path,
4337 O_WRONLY | O_CREAT | truncate_flag | O_CLOEXEC | O_NOFOLLOW,
4338 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
4339 if (fd < 0) {
4340 MYLOGE("%s: %s\n", path, strerror(errno));
4341 return false;
4342 }
4343
4344 TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
4345 close(fd);
4346 return true;
4347}
4348
4349bool redirect_to_file(FILE* redirect, char* path) {
4350 return _redirect_to_file(redirect, path, O_TRUNC);
4351}
4352
4353bool redirect_to_existing_file(FILE* redirect, char* path) {
4354 return _redirect_to_file(redirect, path, O_APPEND);
4355}
4356
4357void dump_route_tables() {
4358 DurationReporter duration_reporter("DUMP ROUTE TABLES");
4359 if (PropertiesHelper::IsDryRun()) return;
4360 const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
4361 ds.DumpFile("RT_TABLES", RT_TABLES_PATH);
4362 FILE* fp = fopen(RT_TABLES_PATH, "re");
4363 if (!fp) {
4364 printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
4365 return;
4366 }
4367 char table[16];
4368 // Each line has an integer (the table number), a space, and a string (the table name). We only
4369 // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
4370 // Add a fixed max limit so this doesn't go awry.
4371 for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
4372 RunCommand("ROUTE TABLE IPv4", {"ip", "-4", "route", "show", "table", table});
4373 RunCommand("ROUTE TABLE IPv6", {"ip", "-6", "route", "show", "table", table});
4374 }
4375 fclose(fp);
4376}
4377
Li Li830179f2022-01-04 12:53:29 -08004378void dump_frozen_cgroupfs(const char *dir, int level,
4379 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4380 DIR *dirp;
4381 struct dirent *d;
4382 char *newpath = nullptr;
4383
4384 dirp = opendir(dir);
4385 if (dirp == nullptr) {
4386 MYLOGE("%s: %s\n", dir, strerror(errno));
4387 return;
4388 }
4389
4390 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4391 if ((d->d_name[0] == '.')
4392 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4393 || (d->d_name[1] == '\0'))) {
4394 continue;
4395 }
4396 if (d->d_type == DT_DIR) {
4397 asprintf(&newpath, "%s/%s/", dir, d->d_name);
4398 if (!newpath) {
4399 continue;
4400 }
4401 if (level == 0 && !strncmp(d->d_name, "uid_", 4)) {
4402 dump_frozen_cgroupfs(newpath, 1, dump_from_fd);
4403 } else if (level == 1 && !strncmp(d->d_name, "pid_", 4)) {
4404 char *freezer = nullptr;
4405 asprintf(&freezer, "%s/%s", newpath, "cgroup.freeze");
4406 if (freezer) {
4407 FILE* fp = fopen(freezer, "r");
4408 if (fp != NULL) {
4409 int frozen;
4410 fscanf(fp, "%d", &frozen);
4411 if (frozen > 0) {
4412 dump_files("", newpath, skip_none, dump_from_fd);
4413 }
4414 fclose(fp);
4415 }
4416 free(freezer);
4417 }
4418 }
4419 }
4420 }
4421 closedir(dirp);
4422}
4423
4424void dump_frozen_cgroupfs() {
Li Li830179f2022-01-04 12:53:29 -08004425 MYLOGD("Adding frozen processes from %s\n", CGROUPFS_DIR);
4426 DurationReporter duration_reporter("FROZEN CGROUPFS");
4427 if (PropertiesHelper::IsDryRun()) return;
4428 dump_frozen_cgroupfs(CGROUPFS_DIR, 0, _add_file_from_fd);
4429}
4430
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004431void Dumpstate::UpdateProgress(int32_t delta_sec) {
4432 if (progress_ == nullptr) {
4433 MYLOGE("UpdateProgress: progress_ not set\n");
4434 return;
4435 }
Rhed Jaobf63d8a2020-07-21 15:42:55 +08004436 // This function updates progress related members of the dumpstate and reports
4437 // progress percentage to the bugreport client. Since it could be called by
4438 // different dump tasks at the same time if the parallel run is enabled, a
4439 // mutex lock is necessary here to synchronize the call.
4440 std::lock_guard<std::recursive_mutex> lock(mutex_);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004441
4442 // Always update progess so stats can be tuned...
Nandana Dutt402a8392019-06-14 14:25:13 +01004443 progress_->Inc(delta_sec);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004444
4445 // ...but only notifiy listeners when necessary.
4446 if (!options_->do_progress_updates) return;
4447
4448 int progress = progress_->Get();
4449 int max = progress_->GetMax();
Nandana Dutt402a8392019-06-14 14:25:13 +01004450 int percent = 100 * progress / max;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004451
Nandana Dutt402a8392019-06-14 14:25:13 +01004452 if (last_reported_percent_progress_ > 0 && percent <= last_reported_percent_progress_) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004453 return;
4454 }
Nandana Dutt402a8392019-06-14 14:25:13 +01004455 last_reported_percent_progress_ = percent;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004456
4457 if (control_socket_fd_ >= 0) {
4458 dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
4459 fsync(control_socket_fd_);
4460 }
4461
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004462 if (listener_ != nullptr) {
Nandana Dutt235c6672019-11-14 15:22:32 +00004463 if (percent % 10 == 0) {
4464 // We don't want to spam logcat, so only log multiples of 10.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004465 MYLOGD("Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004466 } else {
4467 // stderr is ignored on normal invocations, but useful when calling
4468 // /system/bin/dumpstate directly for debuggging.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004469 fprintf(stderr, "Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004470 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004471
4472 listener_->onProgress(percent);
4473 }
4474}
4475
4476void Dumpstate::TakeScreenshot(const std::string& path) {
4477 const std::string& real_path = path.empty() ? screenshot_path_ : path;
4478 int status =
4479 RunCommand("", {"/system/bin/screencap", "-p", real_path},
4480 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
4481 if (status == 0) {
4482 MYLOGD("Screenshot saved on %s\n", real_path.c_str());
4483 } else {
4484 MYLOGE("Failed to take screenshot on %s\n", real_path.c_str());
4485 }
Paul Chang0d2aad72020-02-13 20:04:03 +08004486 if (listener_ != nullptr) {
4487 // Show a visual indication to indicate screenshot is taken via
4488 // IDumpstateListener.onScreenshotTaken()
4489 listener_->onScreenshotTaken(status == 0);
4490 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004491}
4492
4493bool is_dir(const char* pathname) {
4494 struct stat info;
4495 if (stat(pathname, &info) == -1) {
4496 return false;
4497 }
4498 return S_ISDIR(info.st_mode);
4499}
4500
4501time_t get_mtime(int fd, time_t default_mtime) {
4502 struct stat info;
4503 if (fstat(fd, &info) == -1) {
4504 return default_mtime;
4505 }
4506 return info.st_mtime;
4507}