blob: ea3090349e03a608ea826b4a1f847b32f3b00eba [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"
Erik Kline08165202016-05-30 11:55:44 +0900180#define WLUTIL "/vendor/xbin/wlutil"
Vishnu Nair36b4cdb2017-11-17 10:27:05 -0800181#define WMTRACE_DATA_DIR "/data/misc/wmtrace"
Yifan Hong3945e1b2019-10-29 12:59:23 -0700182#define OTA_METADATA_DIR "/metadata/ota"
Yifan Hong0efa7972020-02-03 16:45:02 -0800183#define SNAPSHOTCTL_LOG_DIR "/data/misc/snapshotctl_log"
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +0900184#define LINKERCONFIG_DIR "/linkerconfig"
Calin Juravlef84d3692020-04-28 15:31:12 -0700185#define PACKAGE_DEX_USE_LIST "/data/system/package-dex-usage.list"
Primiano Tuccifaaaafb2021-01-14 12:26:29 +0000186#define SYSTEM_TRACE_SNAPSHOT "/data/misc/perfetto-traces/bugreport/systrace.pftrace"
Li Li2eedd412021-06-30 15:11:53 -0700187#define CGROUPFS_DIR "/sys/fs/cgroup"
Mårten Kongstad60195a72022-09-20 14:14:20 +0200188#define SDK_EXT_INFO "/apex/com.android.sdkext/bin/derive_sdk"
Jeff Sharkey9df29d52023-02-06 14:26:30 -0700189#define DROPBOX_DIR "/data/system/dropbox"
Mårten Kongstad5ad813f2023-09-28 10:09:18 +0200190#define PRINT_FLAGS "/system/bin/printflags"
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700191
Narayan Kamath8f788292017-05-25 13:20:39 +0100192// TODO(narayan): Since this information has to be kept in sync
193// with tombstoned, we should just put it in a common header.
194//
195// File: system/core/debuggerd/tombstoned/tombstoned.cpp
Narayan Kamathbd863722017-06-01 18:50:12 +0100196static const std::string TOMBSTONE_DIR = "/data/tombstones/";
197static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
198static const std::string ANR_DIR = "/data/anr/";
199static const std::string ANR_FILE_PREFIX = "anr_";
Woody Lin20767a92022-11-29 15:50:24 +0800200static const std::string SHUTDOWN_CHECKPOINTS_DIR = "/data/system/shutdown-checkpoints/";
201static const std::string SHUTDOWN_CHECKPOINTS_FILE_PREFIX = "checkpoints-";
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700202
Felipe Lemee844a9d2016-09-21 15:01:39 -0700203// TODO: temporary variables and functions used during C++ refactoring
Nandana Dutt979388e2018-11-30 16:48:55 +0000204
Nandana Dutt5c390032019-03-12 10:52:56 +0000205#define RETURN_IF_USER_DENIED_CONSENT() \
206 if (ds.IsUserConsentDenied()) { \
207 MYLOGE("Returning early as user denied consent to share bugreport with calling app."); \
208 return Dumpstate::RunStatus::USER_CONSENT_DENIED; \
209 }
210
211// Runs func_ptr, but checks user consent before and after running it. Returns USER_CONSENT_DENIED
212// if consent is found to be denied.
213#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(func_ptr, ...) \
214 RETURN_IF_USER_DENIED_CONSENT(); \
215 func_ptr(__VA_ARGS__); \
216 RETURN_IF_USER_DENIED_CONSENT();
217
Rhed Jao5377d792020-07-16 17:37:39 +0800218// Runs func_ptr, and logs a duration report after it's finished.
219#define RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, ...) \
220 { \
221 DurationReporter duration_reporter_in_macro(log_title); \
222 func_ptr(__VA_ARGS__); \
223 }
224
225// Similar with RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK, an additional duration report
226// is output after a slow function is finished.
227#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(log_title, func_ptr, ...) \
228 RETURN_IF_USER_DENIED_CONSENT(); \
229 RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, __VA_ARGS__); \
230 RETURN_IF_USER_DENIED_CONSENT();
231
Chris Morinbc223142022-02-04 14:17:11 -0800232#define WAIT_TASK_WITH_CONSENT_CHECK(future) \
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800233 RETURN_IF_USER_DENIED_CONSENT(); \
Chris Morinbc223142022-02-04 14:17:11 -0800234 WaitForTask(future); \
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800235 RETURN_IF_USER_DENIED_CONSENT();
236
Sahana Raof35ed432019-07-12 10:47:52 +0100237static const char* WAKE_LOCK_NAME = "dumpstate_wakelock";
238
Rhed Jao5377d792020-07-16 17:37:39 +0800239// Names of parallel tasks, they are used for the DumpPool to identify the dump
240// task and the log title of the duration report.
241static const std::string DUMP_TRACES_TASK = "DUMP TRACES";
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800242static const std::string DUMP_INCIDENT_REPORT_TASK = "INCIDENT REPORT";
Aaron Huang24d215d2022-04-27 18:51:16 +0800243static const std::string DUMP_NETSTATS_PROTO_TASK = "DUMP NETSTATS PROTO";
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800244static const std::string DUMP_HALS_TASK = "DUMP HALS";
245static const std::string DUMP_BOARD_TASK = "dumpstate_board()";
Rhed Jaoe017f982020-07-21 17:58:41 +0800246static const std::string DUMP_CHECKINS_TASK = "DUMP CHECKINS";
Kean Mariotti306633e2022-09-05 16:30:47 +0000247static const std::string POST_PROCESS_UI_TRACES_TASK = "POST-PROCESS UI TRACES";
Rhed Jao5377d792020-07-16 17:37:39 +0800248
Nandana Dutt979388e2018-11-30 16:48:55 +0000249namespace android {
250namespace os {
251namespace {
252
253static int Open(std::string path, int flags, mode_t mode = 0) {
254 int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
255 if (fd == -1) {
256 MYLOGE("open(%s, %s)\n", path.c_str(), strerror(errno));
257 }
258 return fd;
259}
260
mhasank2d75c442020-06-11 15:05:25 -0700261static int OpenForWrite(std::string path) {
262 return Open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
263 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
264}
Nandana Dutt979388e2018-11-30 16:48:55 +0000265
266static int OpenForRead(std::string path) {
267 return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
268}
269
270bool CopyFile(int in_fd, int out_fd) {
271 char buf[4096];
272 ssize_t byte_count;
273 while ((byte_count = TEMP_FAILURE_RETRY(read(in_fd, buf, sizeof(buf)))) > 0) {
274 if (!android::base::WriteFully(out_fd, buf, byte_count)) {
275 return false;
276 }
277 }
278 return (byte_count != -1);
279}
280
281static bool CopyFileToFd(const std::string& input_file, int out_fd) {
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000282 MYLOGD("Going to copy file (%s) to %d\n", input_file.c_str(), out_fd);
Nandana Dutt979388e2018-11-30 16:48:55 +0000283
284 // Obtain a handle to the source file.
285 android::base::unique_fd in_fd(OpenForRead(input_file));
286 if (out_fd != -1 && in_fd.get() != -1) {
287 if (CopyFile(in_fd.get(), out_fd)) {
288 return true;
289 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000290 MYLOGE("Failed to copy file: %s\n", strerror(errno));
Nandana Dutt979388e2018-11-30 16:48:55 +0000291 }
292 return false;
293}
294
Nandana Duttd2f5f082019-01-18 17:13:52 +0000295static bool UnlinkAndLogOnError(const std::string& file) {
Nandana Dutt8ae16e62020-03-27 10:20:22 +0000296 if (file.empty()) {
297 return false;
298 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000299 if (unlink(file.c_str())) {
300 MYLOGE("Failed to unlink file (%s): %s\n", file.c_str(), strerror(errno));
Nandana Duttd2f5f082019-01-18 17:13:52 +0000301 return false;
302 }
303 return true;
304}
Nandana Dutt979388e2018-11-30 16:48:55 +0000305
Nikita Ioffea325a572019-05-16 19:49:47 +0100306int64_t GetModuleMetadataVersion() {
307 auto binder = defaultServiceManager()->getService(android::String16("package_native"));
308 if (binder == nullptr) {
309 MYLOGE("Failed to retrieve package_native service");
310 return 0L;
311 }
312 auto package_service = android::interface_cast<content::pm::IPackageManagerNative>(binder);
313 std::string package_name;
314 auto status = package_service->getModuleMetadataPackageName(&package_name);
315 if (!status.isOk()) {
316 MYLOGE("Failed to retrieve module metadata package name: %s", status.toString8().c_str());
317 return 0L;
318 }
Nandana Duttdb379fa2019-10-09 16:54:41 +0100319 MYLOGD("Module metadata package name: %s\n", package_name.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100320 int64_t version_code;
321 status = package_service->getVersionCodeForPackage(android::String16(package_name.c_str()),
322 &version_code);
323 if (!status.isOk()) {
324 MYLOGE("Failed to retrieve module metadata version: %s", status.toString8().c_str());
325 return 0L;
326 }
327 return version_code;
328}
329
mhasank2d75c442020-06-11 15:05:25 -0700330static bool PathExists(const std::string& path) {
331 struct stat sb;
332 return stat(path.c_str(), &sb) == 0;
333}
334
335static bool CopyFileToFile(const std::string& input_file, const std::string& output_file) {
336 if (input_file == output_file) {
337 MYLOGD("Skipping copying bugreport file since the destination is the same (%s)\n",
338 output_file.c_str());
339 return false;
340 }
341 else if (PathExists(output_file)) {
342 MYLOGD("Cannot overwrite an existing file (%s)\n", output_file.c_str());
343 return false;
344 }
345
346 MYLOGD("Going to copy bugreport file (%s) to %s\n", input_file.c_str(), output_file.c_str());
347 android::base::unique_fd out_fd(OpenForWrite(output_file));
348 return CopyFileToFd(input_file, out_fd.get());
349}
350
Nandana Dutt979388e2018-11-30 16:48:55 +0000351} // namespace
352} // namespace os
353} // namespace android
354
Felipe Leme678727a2016-09-21 17:22:11 -0700355static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
Felipe Lemebda15a02016-11-16 17:48:25 -0800356 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
Rhed Jaoe017f982020-07-21 17:58:41 +0800357 long dumpsysTimeoutMs = 0, int out_fd = STDOUT_FILENO) {
358 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs, out_fd);
359}
360static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
361 int out_fd) {
362 return ds.RunDumpsys(title, dumpsysArgs, Dumpstate::DEFAULT_DUMPSYS, 0, out_fd);
Felipe Leme678727a2016-09-21 17:22:11 -0700363}
364static int DumpFile(const std::string& title, const std::string& path) {
365 return ds.DumpFile(title, path);
366}
Felipe Lemee82a27d2016-01-05 13:35:44 -0800367
Felipe Lemee844a9d2016-09-21 15:01:39 -0700368// Relative directory (inside the zip) for all files copied as-is into the bugreport.
369static const std::string ZIP_ROOT_DIR = "FS";
370
Vishnu Naire97d6122018-01-18 13:58:56 -0800371static const std::string kProtoPath = "proto/";
372static const std::string kProtoExt = ".proto";
Jie Song9fbfad02017-06-20 16:29:42 -0700373static const std::string kDumpstateBoardFiles[] = {
374 "dumpstate_board.txt",
Felipe Leme95d6ca52017-08-01 16:35:56 -0700375 "dumpstate_board.bin"
Jie Song9fbfad02017-06-20 16:29:42 -0700376};
377static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
378
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700379static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Lemed071c682016-10-20 16:48:00 -0700380static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700381
Felipe Lemef0292972016-11-22 13:57:05 -0800382static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
383
Narayan Kamath8f788292017-05-25 13:20:39 +0100384/*
Narayan Kamathbd863722017-06-01 18:50:12 +0100385 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
Rhed Jao01dc0c62020-06-03 17:13:30 +0800386 * The returned vector is sorted by the mtimes of the dumps with descending
Chris Morinc2cba7a2022-02-01 17:06:50 -0800387 * order.
Narayan Kamath8f788292017-05-25 13:20:39 +0100388 */
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700389static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
Chris Morinc2cba7a2022-02-01 17:06:50 -0800390 const std::string& file_prefix) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100391 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100392
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700393 if (dump_dir == nullptr) {
394 MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno));
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700395 return std::vector<DumpData>();
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700396 }
397
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700398 std::vector<DumpData> dump_data;
Narayan Kamathbd863722017-06-01 18:50:12 +0100399 struct dirent* entry = nullptr;
400 while ((entry = readdir(dump_dir.get()))) {
401 if (entry->d_type != DT_REG) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100402 continue;
403 }
404
Narayan Kamathbd863722017-06-01 18:50:12 +0100405 const std::string base_name(entry->d_name);
406 if (base_name.find(file_prefix) != 0) {
407 continue;
408 }
409
410 const std::string abs_path = dir_path + base_name;
411 android::base::unique_fd fd(
412 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
413 if (fd == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700414 MYLOGW("Unable to open dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamathbd863722017-06-01 18:50:12 +0100415 break;
416 }
417
418 struct stat st = {};
419 if (fstat(fd, &st) == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700420 MYLOGW("Unable to stat dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamath8f788292017-05-25 13:20:39 +0100421 continue;
422 }
423
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700424 dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700425 }
Rhed Jao01dc0c62020-06-03 17:13:30 +0800426 if (!dump_data.empty()) {
427 std::sort(dump_data.begin(), dump_data.end(),
428 [](const auto& a, const auto& b) { return a.mtime > b.mtime; });
429 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100430
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700431 return dump_data;
Narayan Kamath8f788292017-05-25 13:20:39 +0100432}
433
Narayan Kamathbd863722017-06-01 18:50:12 +0100434static bool AddDumps(const std::vector<DumpData>::const_iterator start,
435 const std::vector<DumpData>::const_iterator end,
436 const char* type_name, const bool add_to_zip) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100437 bool dumped = false;
Narayan Kamathbd863722017-06-01 18:50:12 +0100438 for (auto it = start; it != end; ++it) {
439 const std::string& name = it->name;
440 const int fd = it->fd;
Narayan Kamath8f788292017-05-25 13:20:39 +0100441 dumped = true;
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100442
443 // Seek to the beginning of the file before dumping any data. A given
444 // DumpData entry might be dumped multiple times in the report.
445 //
446 // For example, the most recent ANR entry is dumped to the body of the
447 // main entry and it also shows up as a separate entry in the bugreport
448 // ZIP file.
449 if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) {
450 MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(),
451 strerror(errno));
452 }
453
Chris Morinc2cba7a2022-02-01 17:06:50 -0800454 if (add_to_zip) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800455 if (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd, /* timeout = */ 0ms) != OK) {
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100456 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100457 }
458 } else {
459 dump_file_from_fd(type_name, name.c_str(), fd);
460 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100461 }
462
463 return dumped;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700464}
465
Felipe Leme635ca312016-01-05 14:23:02 -0800466// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700467void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800468 char path[PATH_MAX];
469
470 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
471 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700472 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800473 char linkname[PATH_MAX];
474 ssize_t r = readlink(path, linkname, PATH_MAX);
475 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800476 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800477 return;
478 }
479 linkname[r] = '\0';
480
481 if (mount_points.find(linkname) == mount_points.end()) {
482 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700483 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700484 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
Felipe Leme635ca312016-01-05 14:23:02 -0800485 mount_points.insert(linkname);
486 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800487 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800488 }
489 }
490}
491
492void add_mountinfo() {
Felipe Leme678727a2016-09-21 17:22:11 -0700493 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800494 mount_points.clear();
Felipe Leme46b85da2016-11-21 17:40:45 -0800495 DurationReporter duration_reporter(title, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700496 for_each_pid(do_mountinfo, nullptr);
497 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800498}
499
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700500static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
501{
502 DIR *d;
503 struct dirent *de;
504 char path[PATH_MAX];
505
506 d = opendir(driverpath);
Yi Kong19d5c002018-07-20 13:39:55 -0700507 if (d == nullptr) {
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700508 return;
509 }
510
511 while ((de = readdir(d))) {
512 if (de->d_type != DT_LNK) {
513 continue;
514 }
515 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700516 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700517 }
518
519 closedir(d);
520}
521
Mark Salyzyn326842f2015-04-30 09:49:41 -0700522static bool skip_not_stat(const char *path) {
523 static const char stat[] = "/stat";
524 size_t len = strlen(path);
525 if (path[len - 1] == '/') { /* Directory? */
526 return false;
527 }
528 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
529}
530
Jeff Sharkey9df29d52023-02-06 14:26:30 -0700531static bool skip_wtf_strictmode(const char *path) {
532 if (strstr(path, "_wtf")) {
533 return true;
534 } else if (strstr(path, "_strictmode")) {
535 return true;
536 }
537 return false;
538}
539
Felipe Leme4c2d6632016-09-28 14:32:00 -0700540static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800541 return false;
542}
543
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700544unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700545
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800546//
547// stat offsets
548// Name units description
549// ---- ----- -----------
550// read I/Os requests number of read I/Os processed
551#define __STAT_READ_IOS 0
552// read merges requests number of read I/Os merged with in-queue I/O
553#define __STAT_READ_MERGES 1
554// read sectors sectors number of sectors read
555#define __STAT_READ_SECTORS 2
556// read ticks milliseconds total wait time for read requests
557#define __STAT_READ_TICKS 3
558// write I/Os requests number of write I/Os processed
559#define __STAT_WRITE_IOS 4
560// write merges requests number of write I/Os merged with in-queue I/O
561#define __STAT_WRITE_MERGES 5
562// write sectors sectors number of sectors written
563#define __STAT_WRITE_SECTORS 6
564// write ticks milliseconds total wait time for write requests
565#define __STAT_WRITE_TICKS 7
566// in_flight requests number of I/Os currently in flight
567#define __STAT_IN_FLIGHT 8
568// io_ticks milliseconds total time this block device has been active
569#define __STAT_IO_TICKS 9
570// time_in_queue milliseconds total wait time for all requests
571#define __STAT_IN_QUEUE 10
572#define __STAT_NUMBER_FIELD 11
573//
574// read I/Os, write I/Os
575// =====================
576//
577// These values increment when an I/O request completes.
578//
579// read merges, write merges
580// =========================
581//
582// These values increment when an I/O request is merged with an
583// already-queued I/O request.
584//
585// read sectors, write sectors
586// ===========================
587//
588// These values count the number of sectors read from or written to this
589// block device. The "sectors" in question are the standard UNIX 512-byte
590// sectors, not any device- or filesystem-specific block size. The
591// counters are incremented when the I/O completes.
592#define SECTOR_SIZE 512
593//
594// read ticks, write ticks
595// =======================
596//
597// These values count the number of milliseconds that I/O requests have
598// waited on this block device. If there are multiple I/O requests waiting,
599// these values will increase at a rate greater than 1000/second; for
600// example, if 60 read requests wait for an average of 30 ms, the read_ticks
601// field will increase by 60*30 = 1800.
602//
603// in_flight
604// =========
605//
606// This value counts the number of I/O requests that have been issued to
607// the device driver but have not yet completed. It does not include I/O
608// requests that are in the queue but not yet issued to the device driver.
609//
610// io_ticks
611// ========
612//
613// This value counts the number of milliseconds during which the device has
614// had I/O requests queued.
615//
616// time_in_queue
617// =============
618//
619// This value counts the number of milliseconds that I/O requests have waited
620// on this block device. If there are multiple I/O requests waiting, this
621// value will increase as the product of the number of milliseconds times the
622// number of requests waiting (see "read ticks" above for an example).
623#define S_TO_MS 1000
624//
625
Mark Salyzyn326842f2015-04-30 09:49:41 -0700626static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800627 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700628 bool z;
Yi Kong19d5c002018-07-20 13:39:55 -0700629 char *cp, *buffer = nullptr;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700630 size_t i = 0;
Josh Gao7c4258c2018-06-25 13:40:08 -0700631 FILE *fp = fdopen(dup(fd), "rb");
Mark Salyzyn326842f2015-04-30 09:49:41 -0700632 getline(&buffer, &i, fp);
633 fclose(fp);
634 if (!buffer) {
635 return -errno;
636 }
637 i = strlen(buffer);
638 while ((i > 0) && (buffer[i - 1] == '\n')) {
639 buffer[--i] = '\0';
640 }
641 if (!*buffer) {
642 free(buffer);
643 return 0;
644 }
645 z = true;
646 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800647 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700648 if (fields[i] != 0) {
649 z = false;
650 }
651 }
652 if (z) { /* never accessed */
653 free(buffer);
654 return 0;
655 }
656
Wei Wang509bb5d2017-06-09 14:42:12 -0700657 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
658 path += sizeof(BLK_DEV_SYS_DIR) - 1;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700659 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700660
661 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
662 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
663 "W-wait", "in-fli", "activ", "T-wait", path, buffer);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700664 free(buffer);
665
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800666 if (fields[__STAT_IO_TICKS]) {
667 unsigned long read_perf = 0;
668 unsigned long read_ios = 0;
669 if (fields[__STAT_READ_TICKS]) {
670 unsigned long long divisor = fields[__STAT_READ_TICKS]
671 * fields[__STAT_IO_TICKS];
672 read_perf = ((unsigned long long)SECTOR_SIZE
673 * fields[__STAT_READ_SECTORS]
674 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
675 / divisor;
676 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
677 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
678 / divisor;
679 }
680
681 unsigned long write_perf = 0;
682 unsigned long write_ios = 0;
683 if (fields[__STAT_WRITE_TICKS]) {
684 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
685 * fields[__STAT_IO_TICKS];
686 write_perf = ((unsigned long long)SECTOR_SIZE
687 * fields[__STAT_WRITE_SECTORS]
688 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
689 / divisor;
690 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
691 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
692 / divisor;
693 }
694
695 unsigned queue = (fields[__STAT_IN_QUEUE]
696 + (fields[__STAT_IO_TICKS] >> 1))
697 / fields[__STAT_IO_TICKS];
698
699 if (!write_perf && !write_ios) {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700700 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 -0800701 } else {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700702 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 -0800703 read_ios, write_perf, write_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800704 }
705
706 /* bugreport timeout factor adjustment */
707 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
708 worst_write_perf = write_perf;
709 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700710 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700711 return 0;
712}
713
Yao Chenbe3bbc12018-01-17 16:31:10 -0800714static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
715
Tom Cherryf4472f32020-08-05 09:31:17 -0700716// Returns the actual readable size of the given buffer or -1 on error.
717static long logcat_buffer_readable_size(const std::string& buffer) {
718 std::unique_ptr<logger_list, decltype(&android_logger_list_free)> logger_list{
719 android_logger_list_alloc(0, 0, 0), &android_logger_list_free};
720 auto logger = android_logger_open(logger_list.get(), android_name_to_log_id(buffer.c_str()));
721
722 return android_logger_get_log_readable_size(logger);
723}
724
725// Returns timeout in ms to read a list of buffers.
Yao Chenbe3bbc12018-01-17 16:31:10 -0800726static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
727 unsigned long timeout_ms = 0;
728 for (const auto& buffer : buffers) {
Tom Cherryf4472f32020-08-05 09:31:17 -0700729 long readable_size = logcat_buffer_readable_size(buffer);
730 if (readable_size > 0) {
731 // Engineering margin is ten-fold our guess.
732 timeout_ms += 10 * (readable_size + worst_write_perf) / worst_write_perf;
733 }
Yao Chenbe3bbc12018-01-17 16:31:10 -0800734 }
735 return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700736}
737
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800738// Opens a socket and returns its file descriptor.
739static int open_socket(const char* service);
740
Nandana Duttd2f5f082019-01-18 17:13:52 +0000741Dumpstate::ConsentCallback::ConsentCallback() : result_(UNAVAILABLE), start_time_(Nanotime()) {
742}
743
744android::binder::Status Dumpstate::ConsentCallback::onReportApproved() {
745 std::lock_guard<std::mutex> lock(lock_);
746 result_ = APPROVED;
747 MYLOGD("User approved consent to share bugreport\n");
Paul Chang0d2aad72020-02-13 20:04:03 +0800748
749 // Maybe copy screenshot so calling app can display the screenshot to the user as soon as
750 // consent is granted.
751 if (ds.options_->is_screenshot_copied) {
752 return android::binder::Status::ok();
753 }
754
755 if (!ds.options_->do_screenshot || ds.options_->screenshot_fd.get() == -1 ||
756 !ds.do_early_screenshot_) {
757 return android::binder::Status::ok();
758 }
759
760 bool copy_succeeded = android::os::CopyFileToFd(ds.screenshot_path_,
761 ds.options_->screenshot_fd.get());
762 ds.options_->is_screenshot_copied = copy_succeeded;
763 if (copy_succeeded) {
764 android::os::UnlinkAndLogOnError(ds.screenshot_path_);
765 }
Nandana Duttd2f5f082019-01-18 17:13:52 +0000766 return android::binder::Status::ok();
767}
768
769android::binder::Status Dumpstate::ConsentCallback::onReportDenied() {
770 std::lock_guard<std::mutex> lock(lock_);
771 result_ = DENIED;
772 MYLOGW("User denied consent to share bugreport\n");
773 return android::binder::Status::ok();
774}
775
776UserConsentResult Dumpstate::ConsentCallback::getResult() {
777 std::lock_guard<std::mutex> lock(lock_);
778 return result_;
779}
780
781uint64_t Dumpstate::ConsentCallback::getElapsedTimeMs() const {
Hunter Knepshieldf0a39052020-01-03 14:53:04 -0800782 return (Nanotime() - start_time_) / NANOS_PER_MILLI;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000783}
784
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700785void Dumpstate::PrintHeader() const {
Mårten Kongstad60195a72022-09-20 14:14:20 +0200786 std::string build, fingerprint, radio, bootloader, network, sdkversion;
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700787 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700788
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700789 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
790 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700791 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
792 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
793 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
Mårten Kongstad60195a72022-09-20 14:14:20 +0200794 sdkversion = android::base::GetProperty("ro.build.version.sdk", "(unknown)");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700795 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
Colin Crossf45fa6b2012-03-26 12:38:26 -0700796
Felipe Lemed8b94e52016-12-08 10:21:44 -0800797 printf("========================================================\n");
798 printf("== dumpstate: %s\n", date);
799 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700800
Felipe Lemed8b94e52016-12-08 10:21:44 -0800801 printf("\n");
802 printf("Build: %s\n", build.c_str());
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700803 // NOTE: fingerprint entry format is important for other tools.
Felipe Lemed8b94e52016-12-08 10:21:44 -0800804 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
805 printf("Bootloader: %s\n", bootloader.c_str());
806 printf("Radio: %s\n", radio.c_str());
807 printf("Network: %s\n", network.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100808 int64_t module_metadata_version = android::os::GetModuleMetadataVersion();
809 if (module_metadata_version != 0) {
810 printf("Module Metadata version: %" PRId64 "\n", module_metadata_version);
811 }
Mårten Kongstad60195a72022-09-20 14:14:20 +0200812 printf("Android SDK version: %s\n", sdkversion.c_str());
813 printf("SDK extensions: ");
814 RunCommandToFd(STDOUT_FILENO, "", {SDK_EXT_INFO, "--header"},
815 CommandOptions::WithTimeout(1).Always().DropRoot().Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700816
Felipe Lemed8b94e52016-12-08 10:21:44 -0800817 printf("Kernel: ");
Felipe Lemef0292972016-11-22 13:57:05 -0800818 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
Felipe Lemed8b94e52016-12-08 10:21:44 -0800819 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
Devin Moore09fde8d2023-03-21 16:28:22 +0000820 printf("Bootconfig: ");
821 DumpFileToFd(STDOUT_FILENO, "", "/proc/bootconfig");
Felipe Leme7709f8a2017-12-05 09:30:09 -0800822 printf("Uptime: ");
823 RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"},
824 CommandOptions::WithTimeout(1).Always().Build());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800825 printf("Bugreport format version: %s\n", version_.c_str());
Kevin Jeonfa64e642023-07-27 11:36:41 -0400826 printf(
827 "Dumpstate info: id=%d pid=%d dry_run=%d parallel_run=%d strict_run=%d args=%s "
828 "bugreport_mode=%s\n",
829 id_, pid_, PropertiesHelper::IsDryRun(), PropertiesHelper::IsParallelRun(),
830 PropertiesHelper::IsStrictRun(), options_->args.c_str(),
831 options_->bugreport_mode_string.c_str());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800832 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800833}
834
Felipe Leme24b66ee2016-06-16 10:55:26 -0700835// List of file extensions that can cause a zip file attachment to be rejected by some email
836// service providers.
837static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
838 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
839 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
840 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
841};
842
Vishnu Naire97d6122018-01-18 13:58:56 -0800843status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd,
844 std::chrono::milliseconds timeout = 0ms) {
Felipe Leme24b66ee2016-06-16 10:55:26 -0700845 std::string valid_name = entry_name;
846
847 // Rename extension if necessary.
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -0700848 size_t idx = entry_name.rfind('.');
Felipe Leme24b66ee2016-06-16 10:55:26 -0700849 if (idx != std::string::npos) {
850 std::string extension = entry_name.substr(idx);
851 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
852 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
853 valid_name = entry_name + ".renamed";
854 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
855 }
856 }
857
Felipe Leme6fe9db62016-02-12 09:04:16 -0800858 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
859 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Kevin Jeon9bbe0ac2022-05-05 22:05:43 +0000860 size_t flags = ZipWriter::kCompress | ZipWriter::kDefaultCompression;
861 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), flags,
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700862 get_mtime(fd, ds.now_));
Felipe Leme1d486fe2016-10-14 18:06:47 -0700863 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700864 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700865 ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800866 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800867 }
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000868 bool finished_entry = false;
869 auto finish_entry = [this, &finished_entry] {
870 if (!finished_entry) {
871 // This should only be called when we're going to return an earlier error,
872 // which would've been logged. This may imply the file is already corrupt
873 // and any further logging from FinishEntry is more likely to mislead than
874 // not.
875 this->zip_writer_->FinishEntry();
876 }
877 };
878 auto scope_guard = android::base::make_scope_guard(finish_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -0800879 auto start = std::chrono::steady_clock::now();
880 auto end = start + timeout;
881 struct pollfd pfd = {fd, POLLIN};
Felipe Lemee82a27d2016-01-05 13:35:44 -0800882
Felipe Leme770410d2016-01-26 17:07:14 -0800883 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800884 while (1) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800885 if (timeout.count() > 0) {
886 // lambda to recalculate the timeout.
887 auto time_left_ms = [end]() {
888 auto now = std::chrono::steady_clock::now();
889 auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
890 return std::max(diff.count(), 0LL);
891 };
892
893 int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
894 if (rc < 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000895 MYLOGE("Error in poll while adding from fd to zip entry %s:%s\n",
896 entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800897 return -errno;
898 } else if (rc == 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000899 MYLOGE("Timed out adding from fd to zip entry %s:%s Timeout:%lldms\n",
Vishnu Naire97d6122018-01-18 13:58:56 -0800900 entry_name.c_str(), strerror(errno), timeout.count());
901 return TIMED_OUT;
902 }
903 }
904
Zach Riggle22200402016-08-18 01:01:24 -0400905 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800906 if (bytes_read == 0) {
907 break;
908 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800909 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800910 return -errno;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800911 }
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700912 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800913 if (err) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700914 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800915 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800916 }
917 }
918
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700919 err = zip_writer_->FinishEntry();
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000920 finished_entry = true;
Felipe Leme1d486fe2016-10-14 18:06:47 -0700921 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700922 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800923 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800924 }
925
Vishnu Naire97d6122018-01-18 13:58:56 -0800926 return OK;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800927}
928
Felipe Leme1d486fe2016-10-14 18:06:47 -0700929bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
930 android::base::unique_fd fd(
931 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700932 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800933 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800934 return false;
935 }
936
Vishnu Naire97d6122018-01-18 13:58:56 -0800937 return (AddZipEntryFromFd(entry_name, fd.get()) == OK);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800938}
939
940/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700941static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800942 return (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) == OK) ? 0 : 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800943}
944
Felipe Leme1d486fe2016-10-14 18:06:47 -0700945void Dumpstate::AddDir(const std::string& dir, bool recursive) {
Felipe Leme678727a2016-09-21 17:22:11 -0700946 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
Felipe Leme46b85da2016-11-21 17:40:45 -0800947 DurationReporter duration_reporter(dir, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700948 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800949}
950
Felipe Leme1d486fe2016-10-14 18:06:47 -0700951bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800952 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Kevin Jeon9bbe0ac2022-05-05 22:05:43 +0000953 size_t flags = ZipWriter::kCompress | ZipWriter::kDefaultCompression;
954 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), flags, ds.now_);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700955 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700956 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700957 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800958 return false;
959 }
960
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700961 err = zip_writer_->WriteBytes(content.c_str(), content.length());
Felipe Leme1d486fe2016-10-14 18:06:47 -0700962 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700963 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700964 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800965 return false;
966 }
967
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700968 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700969 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700970 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800971 return false;
972 }
973
974 return true;
975}
976
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800977static void DoKmsg() {
978 struct stat st;
979 if (!stat(PSTORE_LAST_KMSG, &st)) {
980 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
981 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
982 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
983 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
984 } else {
985 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
986 DumpFile("LAST KMSG", "/proc/last_kmsg");
987 }
988}
989
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800990static void DoKernelLogcat() {
Yao Chenbe3bbc12018-01-17 16:31:10 -0800991 unsigned long timeout_ms = logcat_timeout({"kernel"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800992 RunCommand(
993 "KERNEL LOG",
994 {"logcat", "-b", "kernel", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
995 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
996}
997
Nandana Duttdb379fa2019-10-09 16:54:41 +0100998static void DoSystemLogcat(time_t since) {
999 char since_str[80];
1000 strftime(since_str, sizeof(since_str), "%Y-%m-%d %H:%M:%S.000", localtime(&since));
1001
1002 unsigned long timeout_ms = logcat_timeout({"main", "system", "crash"});
1003 RunCommand("SYSTEM LOG",
1004 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v", "-T",
1005 since_str},
1006 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1007}
1008
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001009static void DoRadioLogcat() {
1010 unsigned long timeout_ms = logcat_timeout({"radio"});
1011 RunCommand(
1012 "RADIO LOG",
1013 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1014 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
1015}
1016
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001017static void DoLogcat() {
Vishnu Nair6921f802017-11-22 09:17:23 -08001018 unsigned long timeout_ms;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001019 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
1020 // calculate timeout
Yao Chenbe3bbc12018-01-17 16:31:10 -08001021 timeout_ms = logcat_timeout({"main", "system", "crash"});
Tony Makae737652017-03-30 17:47:09 +01001022 RunCommand("SYSTEM LOG",
Vishnu Nair6921f802017-11-22 09:17:23 -08001023 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1024 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -08001025 timeout_ms = logcat_timeout({"events"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001026 RunCommand(
1027 "EVENT LOG",
1028 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001029 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Yao Chenbe3bbc12018-01-17 16:31:10 -08001030 timeout_ms = logcat_timeout({"stats"});
1031 RunCommand(
1032 "STATS LOG",
1033 {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001034 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001035 DoRadioLogcat();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001036
1037 RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
1038
1039 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001040 RunCommand("LAST LOGCAT", {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable",
1041 "-v", "uid", "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001042}
1043
Mike Ma5c267872019-08-21 11:31:34 -07001044static void DumpIncidentReport() {
Mike Ma5c267872019-08-21 11:31:34 -07001045 const std::string path = ds.bugreport_internal_dir_ + "/tmp_incident_report";
1046 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1047 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1048 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1049 if (fd < 0) {
1050 MYLOGE("Could not open %s to dump incident report.\n", path.c_str());
1051 return;
1052 }
Kevin Jeonfa64e642023-07-27 11:36:41 -04001053 RunCommandToFd(fd, "", {"incident", "-u"},
1054 CommandOptions::WithTimeout(PropertiesHelper::IsStrictRun() ? 20 : 120).Build());
Mike Ma5c267872019-08-21 11:31:34 -07001055 bool empty = 0 == lseek(fd, 0, SEEK_END);
1056 if (!empty) {
1057 // Use a different name from "incident.proto"
1058 // /proto/incident.proto is reserved for incident service dump
1059 // i.e. metadata for debugging.
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001060 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "incident_report" + kProtoExt,
1061 path);
1062 } else {
1063 unlink(path.c_str());
Mike Ma5c267872019-08-21 11:31:34 -07001064 }
Mike Ma5c267872019-08-21 11:31:34 -07001065}
1066
Aaron Huang24d215d2022-04-27 18:51:16 +08001067static void DumpNetstatsProto() {
1068 const std::string path = ds.bugreport_internal_dir_ + "/tmp_netstats_proto";
1069 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1070 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1071 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1072 if (fd < 0) {
1073 MYLOGE("Could not open %s to dump netstats proto.\n", path.c_str());
1074 return;
1075 }
1076 RunCommandToFd(fd, "", {"dumpsys", "netstats", "--proto"},
Kevin Jeon2fb3dd62022-09-28 18:48:55 +00001077 CommandOptions::WithTimeout(5).Build());
Aaron Huang24d215d2022-04-27 18:51:16 +08001078 bool empty = 0 == lseek(fd, 0, SEEK_END);
1079 if (!empty) {
1080 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "netstats" + kProtoExt,
1081 path);
1082 } else {
1083 unlink(path.c_str());
1084 }
1085}
1086
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001087static void MaybeAddSystemTraceToZip() {
1088 // This function copies into the .zip the system trace that was snapshotted
1089 // by the early call to MaybeSnapshotSystemTrace(), if any background
1090 // tracing was happening.
Kean Mariotti853b73a2023-07-27 12:40:30 +00001091 bool system_trace_exists = access(SYSTEM_TRACE_SNAPSHOT, F_OK) == 0;
1092 if (!system_trace_exists) {
1093 // No background trace was happening at the time MaybeSnapshotSystemTrace() was invoked.
1094 if (!PropertiesHelper::IsUserBuild()) {
1095 MYLOGI(
1096 "No system traces found. Check for previously uploaded traces by looking for "
1097 "go/trace-uuid in logcat")
1098 }
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001099 return;
1100 }
1101 ds.AddZipEntry(
1102 ZIP_ROOT_DIR + SYSTEM_TRACE_SNAPSHOT,
1103 SYSTEM_TRACE_SNAPSHOT);
1104 android::os::UnlinkAndLogOnError(SYSTEM_TRACE_SNAPSHOT);
1105}
1106
Sunny Goyal35949782019-11-19 15:54:36 -08001107static void DumpVisibleWindowViews() {
Sunny Goyal35949782019-11-19 15:54:36 -08001108 DurationReporter duration_reporter("VISIBLE WINDOW VIEWS");
1109 const std::string path = ds.bugreport_internal_dir_ + "/tmp_visible_window_views";
1110 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1111 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1112 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1113 if (fd < 0) {
1114 MYLOGE("Could not open %s to dump visible views.\n", path.c_str());
1115 return;
1116 }
1117 RunCommandToFd(fd, "", {"cmd", "window", "dump-visible-window-views"},
Kevin Jeon774abde2022-09-28 18:20:43 +00001118 CommandOptions::WithTimeout(10).Build());
Sunny Goyal35949782019-11-19 15:54:36 -08001119 bool empty = 0 == lseek(fd, 0, SEEK_END);
1120 if (!empty) {
1121 ds.AddZipEntry("visible_windows.zip", path);
1122 } else {
1123 MYLOGW("Failed to dump visible windows\n");
1124 }
1125 unlink(path.c_str());
1126}
1127
Jayachandran Ca94c7172017-06-10 15:08:12 -07001128static void DumpIpTablesAsRoot() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001129 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
1130 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +09001131 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001132 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +09001133 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
1134 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
1135 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
1136 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001137}
1138
Woody Lin20767a92022-11-29 15:50:24 +08001139static void DumpShutdownCheckpoints() {
1140 const bool shutdown_checkpoints_dumped = AddDumps(
1141 ds.shutdown_checkpoints_.begin(), ds.shutdown_checkpoints_.end(),
1142 "SHUTDOWN CHECKPOINTS", false /* add_to_zip */);
1143 if (!shutdown_checkpoints_dumped) {
1144 printf("*** NO SHUTDOWN CHECKPOINTS to dump in %s\n\n",
1145 SHUTDOWN_CHECKPOINTS_DIR.c_str());
1146 }
1147}
1148
David Andersond9ba4752018-12-11 18:26:59 -08001149static void DumpDynamicPartitionInfo() {
1150 if (!::android::base::GetBoolProperty("ro.boot.dynamic_partitions", false)) {
1151 return;
1152 }
1153
1154 RunCommand("LPDUMP", {"lpdump", "--all"});
David Anderson6650ade2019-10-02 15:18:59 -07001155 RunCommand("DEVICE-MAPPER", {"gsid", "dump-device-mapper"});
David Andersond9ba4752018-12-11 18:26:59 -08001156}
1157
Chris Morin5a50d482022-02-01 17:41:18 -08001158static void AddAnrTraceDir(const std::string& anr_traces_dir) {
Narayan Kamath8f788292017-05-25 13:20:39 +01001159 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
1160 anr_traces_dir.c_str());
1161
1162 // If we're here, dump_traces_path will always be a temporary file
1163 // (created with mkostemp or similar) that contains dumps taken earlier
1164 // on in the process.
1165 if (dump_traces_path != nullptr) {
Chris Morin5a50d482022-02-01 17:41:18 -08001166 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
1167 dump_traces_path);
1168 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
Narayan Kamath8f788292017-05-25 13:20:39 +01001169
1170 const int ret = unlink(dump_traces_path);
1171 if (ret == -1) {
1172 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
1173 strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -07001174 }
1175 }
1176
Narayan Kamathbd863722017-06-01 18:50:12 +01001177 // Add a specific message for the first ANR Dump.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001178 if (ds.anr_data_.size() > 0) {
Chris Morin5a50d482022-02-01 17:41:18 -08001179 // The "last" ANR will always be present in the body of the main entry.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001180 AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1,
Chris Morin5a50d482022-02-01 17:41:18 -08001181 "VM TRACES AT LAST ANR", false /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001182
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001183 // Historical ANRs are always included as separate entries in the bugreport zip file.
Chris Morin5a50d482022-02-01 17:41:18 -08001184 AddDumps(ds.anr_data_.begin(), ds.anr_data_.end(),
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001185 "HISTORICAL ANR", true /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001186 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +01001187 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
1188 }
1189}
1190
1191static void AddAnrTraceFiles() {
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001192 std::string anr_traces_dir = "/data/anr";
Narayan Kamath8f788292017-05-25 13:20:39 +01001193
Chris Morin5a50d482022-02-01 17:41:18 -08001194 AddAnrTraceDir(anr_traces_dir);
Narayan Kamath8f788292017-05-25 13:20:39 +01001195
Makoto Onuki83ec63f2019-01-31 17:08:59 -08001196 RunCommand("ANR FILES", {"ls", "-lt", ANR_DIR});
1197
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001198 // Slow traces for slow operations.
Felipe Lemee184f662016-10-27 10:04:47 -07001199 struct stat st;
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001200 int i = 0;
1201 while (true) {
1202 const std::string slow_trace_path =
1203 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
1204 if (stat(slow_trace_path.c_str(), &st)) {
1205 // No traces file at this index, done with the files.
1206 break;
Felipe Lemee184f662016-10-27 10:04:47 -07001207 }
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001208 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
1209 i++;
Felipe Lemee184f662016-10-27 10:04:47 -07001210 }
1211}
1212
Wei Wang509bb5d2017-06-09 14:42:12 -07001213static void DumpBlockStatFiles() {
1214 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -07001215
Wei Wang1dc1ef52017-06-12 11:28:37 -07001216 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
1217
1218 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001219 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1220 return;
1221 }
1222
1223 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -07001224 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001225 if ((d->d_name[0] == '.')
1226 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1227 || (d->d_name[1] == '\0'))) {
1228 continue;
1229 }
1230 const std::string new_path =
1231 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1232 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1233 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1234 printf("\n");
1235 }
Wei Wang1dc1ef52017-06-12 11:28:37 -07001236 return;
Wei Wang509bb5d2017-06-09 14:42:12 -07001237}
Jayachandran Ca94c7172017-06-10 15:08:12 -07001238
1239static void DumpPacketStats() {
1240 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
Jayachandran Ca94c7172017-06-10 15:08:12 -07001241}
1242
1243static void DumpIpAddrAndRules() {
1244 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
1245 RunCommand("NETWORK INTERFACES", {"ip", "link"});
1246 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1247 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1248 RunCommand("IP RULES", {"ip", "rule", "show"});
1249 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1250}
1251
Nandana Dutt5c390032019-03-12 10:52:56 +00001252static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, int priority,
1253 std::chrono::milliseconds timeout,
1254 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001255 auto start = std::chrono::steady_clock::now();
Vishnu Naire97d6122018-01-18 13:58:56 -08001256 sp<android::IServiceManager> sm = defaultServiceManager();
1257 Dumpsys dumpsys(sm.get());
Vishnu Naire97d6122018-01-18 13:58:56 -08001258 Vector<String16> args;
1259 Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
Vishnu Naire97d6122018-01-18 13:58:56 -08001260 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1261 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001262 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001263 std::string path(title);
1264 path.append(" - ").append(String8(service).c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -08001265 size_t bytes_written = 0;
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001266 if (PropertiesHelper::IsDryRun()) {
1267 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1268 dumpsys.writeDumpFooter(STDOUT_FILENO, service, std::chrono::milliseconds(1));
1269 } else {
Devin Mooref492c1a2023-03-15 19:19:03 +00001270 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP | Dumpsys::TYPE_PID |
1271 Dumpsys::TYPE_CLIENTS | Dumpsys::TYPE_THREAD,
Devin Mooreae68df22023-02-24 20:59:51 +00001272 service, args);
1273 if (status == OK) {
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001274 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1275 std::chrono::duration<double> elapsed_seconds;
1276 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH &&
1277 service == String16("meminfo")) {
1278 // Use a longer timeout for meminfo, since 30s is not always enough.
1279 status = dumpsys.writeDump(STDOUT_FILENO, service, 60s,
1280 /* as_proto = */ false, elapsed_seconds,
1281 bytes_written);
1282 } else {
1283 status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
1284 /* as_proto = */ false, elapsed_seconds,
1285 bytes_written);
1286 }
1287 dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
1288 bool dump_complete = (status == OK);
1289 dumpsys.stopDumpThread(dump_complete);
Devin Moorecdfa4602023-03-16 20:49:39 +00001290 } else {
1291 MYLOGE("Failed to start dump thread for service: %s, status: %d",
1292 String8(service).c_str(), status);
Gavin Corkeryfac7e2b2021-07-08 22:39:02 +01001293 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001294 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001295
1296 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1297 std::chrono::steady_clock::now() - start);
1298 if (elapsed_duration > timeout) {
1299 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1300 elapsed_duration.count());
1301 break;
1302 }
1303 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001304 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001305}
1306
Vishnu Nair64afc022018-02-01 15:29:34 -08001307static void RunDumpsysText(const std::string& title, int priority,
1308 std::chrono::milliseconds timeout,
1309 std::chrono::milliseconds service_timeout) {
1310 DurationReporter duration_reporter(title);
1311 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1312 fsync(STDOUT_FILENO);
1313 RunDumpsysTextByPriority(title, priority, timeout, service_timeout);
1314}
1315
1316/* Dump all services registered with Normal or Default priority. */
Nandana Dutt5c390032019-03-12 10:52:56 +00001317static Dumpstate::RunStatus RunDumpsysTextNormalPriority(const std::string& title,
1318 std::chrono::milliseconds timeout,
1319 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001320 DurationReporter duration_reporter(title);
1321 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1322 fsync(STDOUT_FILENO);
1323 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout,
1324 service_timeout);
Nandana Dutt5c390032019-03-12 10:52:56 +00001325
1326 RETURN_IF_USER_DENIED_CONSENT();
1327
1328 return RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1329 service_timeout);
Vishnu Nair64afc022018-02-01 15:29:34 -08001330}
1331
Nandana Dutt5c390032019-03-12 10:52:56 +00001332static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priority,
1333 std::chrono::milliseconds timeout,
1334 std::chrono::milliseconds service_timeout) {
Vishnu Naire97d6122018-01-18 13:58:56 -08001335 sp<android::IServiceManager> sm = defaultServiceManager();
1336 Dumpsys dumpsys(sm.get());
1337 Vector<String16> args;
1338 Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
1339 DurationReporter duration_reporter(title);
1340
1341 auto start = std::chrono::steady_clock::now();
1342 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
1343 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001344 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001345 std::string path(kProtoPath);
1346 path.append(String8(service).c_str());
1347 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
1348 path.append("_CRITICAL");
1349 } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
1350 path.append("_HIGH");
1351 }
1352 path.append(kProtoExt);
Steven Morelandcbd69fc2021-07-20 20:45:43 +00001353 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP, service, args);
Vishnu Naire97d6122018-01-18 13:58:56 -08001354 if (status == OK) {
1355 status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
1356 bool dumpTerminated = (status == OK);
1357 dumpsys.stopDumpThread(dumpTerminated);
1358 }
1359 ZipWriter::FileEntry file_entry;
1360 ds.zip_writer_->GetLastEntry(&file_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -08001361
1362 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1363 std::chrono::steady_clock::now() - start);
1364 if (elapsed_duration > timeout) {
1365 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1366 elapsed_duration.count());
1367 break;
1368 }
1369 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001370 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001371}
1372
Nandana Dutta7db6342018-11-21 14:53:34 +00001373// Runs dumpsys on services that must dump first and will take less than 100ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001374static Dumpstate::RunStatus RunDumpsysCritical() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001375 RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1376 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Nandana Dutt5c390032019-03-12 10:52:56 +00001377
1378 RETURN_IF_USER_DENIED_CONSENT();
1379
1380 return RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1381 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Vishnu Nair780b1282017-10-10 13:57:24 -07001382}
1383
1384// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001385static Dumpstate::RunStatus RunDumpsysHigh() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001386 // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
1387 // high priority. Reduce timeout once they are able to dump in a shorter time or
1388 // moved to a parallel task.
1389 RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1390 /* timeout= */ 90s, /* service_timeout= */ 30s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001391
1392 RETURN_IF_USER_DENIED_CONSENT();
1393
1394 return RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1395 /* timeout= */ 5s, /* service_timeout= */ 1s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001396}
1397
1398// Runs dumpsys on services that must dump but can take up to 10s to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001399static Dumpstate::RunStatus RunDumpsysNormal() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001400 RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001401
1402 RETURN_IF_USER_DENIED_CONSENT();
1403
1404 return RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1405 /* timeout= */ 90s, /* service_timeout= */ 10s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001406}
1407
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001408/*
1409 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1410 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1411 * if it's not running in the parallel task.
1412 */
1413static void DumpHals(int out_fd = STDOUT_FILENO) {
Yifan Hong30528a22020-08-07 18:24:06 -07001414 RunCommand("HARDWARE HALS", {"lshal", "--all", "--types=all"},
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001415 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build(),
1416 false, out_fd);
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001417
Steven Moreland44cd9482018-01-04 16:24:13 -08001418 using android::hidl::manager::V1_0::IServiceManager;
1419 using android::hardware::defaultServiceManager;
1420
1421 sp<IServiceManager> sm = defaultServiceManager();
1422 if (sm == nullptr) {
1423 MYLOGE("Could not retrieve hwservicemanager to dump hals.\n");
1424 return;
1425 }
1426
1427 auto ret = sm->list([&](const auto& interfaces) {
1428 for (const std::string& interface : interfaces) {
1429 std::string cleanName = interface;
Steven Morelandc6b1fc22023-07-26 23:53:58 +00001430 std::replace_if(
1431 cleanName.begin(), cleanName.end(),
1432 [](char c) {
1433 return !isalnum(c) && std::string("@-_.").find(c) == std::string::npos;
1434 },
1435 '_');
Nandana Dutt979388e2018-11-30 16:48:55 +00001436 const std::string path = ds.bugreport_internal_dir_ + "/lshal_debug_" + cleanName;
Steven Moreland44cd9482018-01-04 16:24:13 -08001437
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001438 bool empty = false;
Steven Moreland44cd9482018-01-04 16:24:13 -08001439 {
1440 auto fd = android::base::unique_fd(
1441 TEMP_FAILURE_RETRY(open(path.c_str(),
1442 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1443 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1444 if (fd < 0) {
1445 MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str());
1446 continue;
1447 }
1448 RunCommandToFd(fd,
1449 "",
Steven Morelandc81cd3c2018-01-18 14:36:26 -08001450 {"lshal", "debug", "-E", interface},
Steven Moreland44cd9482018-01-04 16:24:13 -08001451 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1452
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001453 empty = 0 == lseek(fd, 0, SEEK_END);
Steven Moreland44cd9482018-01-04 16:24:13 -08001454 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001455 if (!empty) {
1456 ds.EnqueueAddZipEntryAndCleanupIfNeeded("lshal-debug/" + cleanName + ".txt",
1457 path);
1458 } else {
1459 unlink(path.c_str());
1460 }
Steven Moreland44cd9482018-01-04 16:24:13 -08001461 }
1462 });
1463
1464 if (!ret.isOk()) {
1465 MYLOGE("Could not list hals from hwservicemanager.\n");
1466 }
1467}
1468
Devin Moore8df81bb2022-06-08 22:47:02 +00001469// Dump all of the files that make up the vendor interface.
1470// See the files listed in dumpFileList() for the latest list of files.
1471static void DumpVintf() {
Devin Moore16271d92022-09-22 18:28:48 +00001472
1473 const std::string sku = android::base::GetProperty("ro.boot.product.hardware.sku", "");
1474 const auto vintfFiles = android::vintf::details::dumpFileList(sku);
Devin Moore8df81bb2022-06-08 22:47:02 +00001475 for (const auto vintfFile : vintfFiles) {
1476 struct stat st;
1477 if (stat(vintfFile.c_str(), &st) == 0) {
1478 if (S_ISDIR(st.st_mode)) {
1479 ds.AddDir(vintfFile, true /* recursive */);
1480 } else {
1481 ds.EnqueueAddZipEntryAndCleanupIfNeeded(ZIP_ROOT_DIR + vintfFile,
1482 vintfFile);
1483 }
1484 }
1485 }
1486}
1487
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001488static void DumpExternalFragmentationInfo() {
1489 struct stat st;
1490 if (stat("/proc/buddyinfo", &st) != 0) {
1491 MYLOGE("Unable to dump external fragmentation info\n");
1492 return;
1493 }
1494
1495 printf("------ EXTERNAL FRAGMENTATION INFO ------\n");
1496 std::ifstream ifs("/proc/buddyinfo");
1497 auto unusable_index_regex = std::regex{"Node\\s+([0-9]+),\\s+zone\\s+(\\S+)\\s+(.*)"};
1498 for (std::string line; std::getline(ifs, line);) {
1499 std::smatch match_results;
1500 if (std::regex_match(line, match_results, unusable_index_regex)) {
1501 std::stringstream free_pages(std::string{match_results[3]});
1502 std::vector<int> free_pages_per_order(std::istream_iterator<int>{free_pages},
1503 std::istream_iterator<int>());
1504
1505 int total_free_pages = 0;
1506 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1507 total_free_pages += (free_pages_per_order[i] * std::pow(2, i));
1508 }
1509
1510 printf("Node %s, zone %8s", match_results[1].str().c_str(),
1511 match_results[2].str().c_str());
1512
1513 int usable_free_pages = total_free_pages;
1514 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1515 auto unusable_index = (total_free_pages - usable_free_pages) /
1516 static_cast<double>(total_free_pages);
1517 printf(" %5.3f", unusable_index);
1518 usable_free_pages -= (free_pages_per_order[i] * std::pow(2, i));
1519 }
1520
1521 printf("\n");
1522 }
1523 }
1524 printf("\n");
1525}
1526
mhasankd451a472020-05-26 18:02:39 -07001527static void DumpstateLimitedOnly() {
1528 // Trimmed-down version of dumpstate to only include a whitelisted
1529 // set of logs (system log, event log, and system server / system app
1530 // crashes, and networking logs). See b/136273873 and b/138459828
1531 // for context.
1532 DurationReporter duration_reporter("DUMPSTATE");
1533 unsigned long timeout_ms;
1534 // calculate timeout
1535 timeout_ms = logcat_timeout({"main", "system", "crash"});
1536 RunCommand("SYSTEM LOG",
1537 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1538 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1539 timeout_ms = logcat_timeout({"events"});
1540 RunCommand(
1541 "EVENT LOG",
1542 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1543 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1544
1545 printf("========================================================\n");
1546 printf("== Networking Service\n");
1547 printf("========================================================\n");
1548
1549 RunDumpsys("DUMPSYS NETWORK_SERVICE_LIMITED", {"wifi", "-a"},
1550 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hugo Benichiaa162682020-10-30 23:28:56 +09001551 RunDumpsys("DUMPSYS CONNECTIVITY REQUESTS", {"connectivity", "requests"},
1552 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
mhasankd451a472020-05-26 18:02:39 -07001553
1554 printf("========================================================\n");
1555 printf("== Dropbox crashes\n");
1556 printf("========================================================\n");
1557
1558 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1559 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1560
1561 printf("========================================================\n");
1562 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1563 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1564 printf("========================================================\n");
1565 printf("== dumpstate: done (id %d)\n", ds.id_);
1566 printf("========================================================\n");
1567}
1568
Rhed Jaoe017f982020-07-21 17:58:41 +08001569/*
1570 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1571 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1572 * if it's not running in the parallel task.
1573 */
1574static void DumpCheckins(int out_fd = STDOUT_FILENO) {
1575 dprintf(out_fd, "========================================================\n");
1576 dprintf(out_fd, "== Checkins\n");
1577 dprintf(out_fd, "========================================================\n");
1578
1579 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"}, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001580 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"}, out_fd);
1581 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"}, out_fd);
1582 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"}, out_fd);
1583 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"}, out_fd);
1584}
1585
1586/*
1587 * Runs dumpsys on activity service to dump all application activities, services
1588 * and providers in the device.
1589 *
1590 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1591 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1592 * if it's not running in the parallel task.
1593 */
1594static void DumpAppInfos(int out_fd = STDOUT_FILENO) {
1595 dprintf(out_fd, "========================================================\n");
1596 dprintf(out_fd, "== Running Application Activities\n");
1597 dprintf(out_fd, "========================================================\n");
1598
1599 // The following dumpsys internally collects output from running apps, so it can take a long
1600 // time. So let's extend the timeout.
1601
1602 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1603
1604 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1605
1606 dprintf(out_fd, "========================================================\n");
1607 dprintf(out_fd, "== Running Application Services (platform)\n");
1608 dprintf(out_fd, "========================================================\n");
1609
1610 RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
1611 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1612
1613 dprintf(out_fd, "========================================================\n");
1614 dprintf(out_fd, "== Running Application Services (non-platform)\n");
1615 dprintf(out_fd, "========================================================\n");
1616
1617 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1618 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1619
1620 dprintf(out_fd, "========================================================\n");
1621 dprintf(out_fd, "== Running Application Providers (platform)\n");
1622 dprintf(out_fd, "========================================================\n");
1623
1624 RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
Rhed Jaob049f182021-01-11 21:08:43 +08001625 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001626
1627 dprintf(out_fd, "========================================================\n");
1628 dprintf(out_fd, "== Running Application Providers (non-platform)\n");
1629 dprintf(out_fd, "========================================================\n");
1630
1631 RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1632 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1633}
1634
Nandana Dutt5c390032019-03-12 10:52:56 +00001635// Dumps various things. Returns early with status USER_CONSENT_DENIED if user denies consent
1636// via the consent they are shown. Ignores other errors that occur while running various
1637// commands. The consent checking is currently done around long running tasks, which happen to
1638// be distributed fairly evenly throughout the function.
Kean Mariotti306633e2022-09-05 16:30:47 +00001639Dumpstate::RunStatus Dumpstate::dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001640 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001641
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001642 // Enqueue slow functions into the thread pool, if the parallel run is enabled.
Aaron Huang24d215d2022-04-27 18:51:16 +08001643 std::future<std::string> dump_hals, dump_incident_report, dump_board, dump_checkins,
Kean Mariotti306633e2022-09-05 16:30:47 +00001644 dump_netstats_report, post_process_ui_traces;
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001645 if (ds.dump_pool_) {
1646 // Pool was shutdown in DumpstateDefaultAfterCritical method in order to
Kean Mariotti306633e2022-09-05 16:30:47 +00001647 // drop root user. Restarts it.
1648 ds.dump_pool_->start(/* thread_counts = */3);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001649
Chris Morinbc223142022-02-04 14:17:11 -08001650 dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
1651 dump_incident_report = ds.dump_pool_->enqueueTask(
1652 DUMP_INCIDENT_REPORT_TASK, &DumpIncidentReport);
Aaron Huang24d215d2022-04-27 18:51:16 +08001653 dump_netstats_report = ds.dump_pool_->enqueueTask(
1654 DUMP_NETSTATS_PROTO_TASK, &DumpNetstatsProto);
Chris Morinbc223142022-02-04 14:17:11 -08001655 dump_board = ds.dump_pool_->enqueueTaskWithFd(
1656 DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
1657 dump_checkins = ds.dump_pool_->enqueueTaskWithFd(DUMP_CHECKINS_TASK, &DumpCheckins, _1);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001658 }
1659
Nandana Dutt5c390032019-03-12 10:52:56 +00001660 // Dump various things. Note that anything that takes "long" (i.e. several seconds) should
1661 // check intermittently (if it's intrerruptable like a foreach on pids) and/or should be wrapped
1662 // in a consent check (via RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK).
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001663 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001664 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001665 DumpBlockStatFiles();
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001666 DumpFile("MEMORY INFO", "/proc/meminfo");
1667 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001668 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001669
Kevin Jeon947922b2022-09-21 00:29:18 +00001670 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "BUGREPORT_PROCDUMP", {"bugreport_procdump"},
1671 CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001672
Sunny Goyal35949782019-11-19 15:54:36 -08001673 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpVisibleWindowViews);
1674
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001675 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1676 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1677 DumpFile("SLAB INFO", "/proc/slabinfo");
1678 DumpFile("ZONEINFO", "/proc/zoneinfo");
1679 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1680 DumpFile("BUDDYINFO", "/proc/buddyinfo");
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001681 DumpExternalFragmentationInfo();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001682
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001683 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001684
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001685 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001686 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001687
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001688 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001689 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_hals));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001690 } else {
1691 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_HALS_TASK, DumpHals);
1692 }
Steven Moreland81b429e2017-01-31 19:50:46 -08001693
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001694 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001695 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001696 struct stat s;
1697 if (stat("/proc/modules", &s) != 0) {
1698 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1699 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001700 RunCommand("LSMOD", {"lsmod"});
Woody Linc198f252021-05-04 16:37:11 +08001701 RunCommand("MODULES INFO",
1702 {"sh", "-c", "cat /proc/modules | cut -d' ' -f1 | "
1703 " while read MOD ; do echo modinfo:$MOD ; modinfo $MOD ; "
1704 "done"}, CommandOptions::AS_ROOT);
Felipe Lemee4eca582016-06-10 17:48:08 -07001705 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001706
Tom Cherryb87dbfa2020-07-28 11:28:53 -07001707 if (android::base::GetBoolProperty("ro.logd.kernel", false)) {
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001708 DoKernelLogcat();
1709 } else {
1710 do_dmesg();
1711 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001712
Devin Moore8df81bb2022-06-08 22:47:02 +00001713 DumpVintf();
1714
Felipe Lemef0292972016-11-22 13:57:05 -08001715 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001716
Jeff Brown1dc94e32014-09-11 14:15:27 -07001717 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001718 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001719
Jack Yu5a6b2e22020-08-14 18:13:35 +08001720 /* Dump Nfc NCI logs */
1721 ds.AddDir("/data/misc/nfc/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001722
Paul Chang0d2aad72020-02-13 20:04:03 +08001723 if (ds.options_->do_screenshot && !ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001724 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001725 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001726 }
1727
Felipe Lemee184f662016-10-27 10:04:47 -07001728 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001729
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001730 MaybeAddSystemTraceToZip();
1731
Narayan Kamath8f788292017-05-25 13:20:39 +01001732 // NOTE: tombstones are always added as separate entries in the zip archive
1733 // and are not interspersed with the main report.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001734 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
Narayan Kamathbd863722017-06-01 18:50:12 +01001735 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001736 if (!tombstones_dumped) {
1737 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001738 }
1739
Jayachandran Ca94c7172017-06-10 15:08:12 -07001740 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001741
Lorenzo Colitti807f2dd2022-05-27 12:48:37 +09001742 RunDumpsys("EBPF MAP STATS", {"connectivity", "trafficcontroller"});
Chenbo Feng276a3b62018-08-07 11:44:49 -07001743
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001744 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001745
Woody Lin20767a92022-11-29 15:50:24 +08001746 DumpShutdownCheckpoints();
1747
Jayachandran Ca94c7172017-06-10 15:08:12 -07001748 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001749
1750 dump_route_tables();
1751
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001752 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1753 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1754 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001755
Nandana Dutt5c390032019-03-12 10:52:56 +00001756 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysHigh);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001757
Chiachang Wang668ede42021-05-17 17:14:20 +08001758 // The dump mechanism in connectivity is refactored due to modularization work. Connectivity can
1759 // only register with a default priority(NORMAL priority). Dumpstate has to call connectivity
1760 // dump with priority parameters to dump high priority information.
1761 RunDumpsys("SERVICE HIGH connectivity", {"connectivity", "--dump-priority", "HIGH"},
1762 CommandOptions::WithTimeout(10).Build());
1763
Elliott Hughes23ccc622017-02-28 10:14:22 -08001764 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001765
Joe Onoratod38bc3a2023-06-29 15:48:28 -07001766 DumpFile("SYSTEM BUILD-TIME RELEASE FLAGS", "/system/etc/build_flags.json");
1767 DumpFile("SYSTEM_EXT BUILD-TIME RELEASE FLAGS", "/system_ext/etc/build_flags.json");
1768 DumpFile("PRODUCT BUILD-TIME RELEASE FLAGS", "/product/etc/build_flags.json");
1769 DumpFile("VENDOR BUILD-TIME RELEASE FLAGS", "/vendor/etc/build_flags.json");
1770
Mårten Kongstad5ad813f2023-09-28 10:09:18 +02001771 RunCommand("ACONFIG FLAGS", {PRINT_FLAGS},
1772 CommandOptions::WithTimeout(10).Always().DropRoot().Build());
Joe Onoratod38bc3a2023-06-29 15:48:28 -07001773
Jin Qianf334d662017-10-10 14:41:37 -07001774 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001775
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001776 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001777
Colin Crossf45fa6b2012-03-26 12:38:26 -07001778 /* Binder state is expensive to look at as it uses a lot of memory. */
Hridya Valsaraju920ba712020-02-09 16:27:01 -08001779 std::string binder_logs_dir = access("/dev/binderfs/binder_logs", R_OK) ?
1780 "/sys/kernel/debug/binder" : "/dev/binderfs/binder_logs";
1781
1782 DumpFile("BINDER FAILED TRANSACTION LOG", binder_logs_dir + "/failed_transaction_log");
1783 DumpFile("BINDER TRANSACTION LOG", binder_logs_dir + "/transaction_log");
1784 DumpFile("BINDER TRANSACTIONS", binder_logs_dir + "/transactions");
1785 DumpFile("BINDER STATS", binder_logs_dir + "/stats");
1786 DumpFile("BINDER STATE", binder_logs_dir + "/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001787
Yifan Hongd90cc652020-02-08 16:52:02 -08001788 ds.AddDir(SNAPSHOTCTL_LOG_DIR, false);
1789
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001790 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001791 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_board));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001792 } else {
1793 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
1794 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001795
Steven Moreland7440ddb2016-12-15 16:13:39 -08001796 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001797 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1798 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001799 // su does not exist on user builds, so try running without it.
1800 // This way any implementations of vril-dump that do not require
1801 // root can run on user builds.
1802 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001803 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001804 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001805 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001806 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001807 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001808 }
1809
Felipe Lemed8b94e52016-12-08 10:21:44 -08001810 printf("========================================================\n");
1811 printf("== Android Framework Services\n");
1812 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001813
Nandana Dutt5c390032019-03-12 10:52:56 +00001814 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001815
Jack He91ff2fe2021-02-18 18:23:43 -08001816 /* Dump Bluetooth HCI logs after getting bluetooth_manager dumpsys */
1817 ds.AddDir("/data/misc/bluetooth/logs", true);
1818
Rhed Jaoe017f982020-07-21 17:58:41 +08001819 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001820 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_checkins));
Rhed Jaoe017f982020-07-21 17:58:41 +08001821 } else {
1822 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_CHECKINS_TASK, DumpCheckins);
1823 }
Dianne Hackborn02bea972013-06-26 18:59:09 -07001824
Rhed Jaoc5f7ec32020-12-22 22:11:08 +08001825 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpAppInfos);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001826
Adrian Roos8b397ab2017-04-04 16:35:44 -07001827 printf("========================================================\n");
1828 printf("== Dropbox crashes\n");
1829 printf("========================================================\n");
1830
1831 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1832 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1833
Felipe Lemed8b94e52016-12-08 10:21:44 -08001834 printf("========================================================\n");
1835 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1836 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1837 printf("========================================================\n");
1838 printf("== dumpstate: done (id %d)\n", ds.id_);
1839 printf("========================================================\n");
Bookatz38472142018-09-28 10:20:24 -07001840
1841 printf("========================================================\n");
1842 printf("== Obtaining statsd metadata\n");
1843 printf("========================================================\n");
1844 // This differs from the usual dumpsys stats, which is the stats report data.
1845 RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
Mike Ma5c267872019-08-21 11:31:34 -07001846
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +09001847 // Add linker configuration directory
1848 ds.AddDir(LINKERCONFIG_DIR, true);
1849
Li Li830179f2022-01-04 12:53:29 -08001850 /* Dump frozen cgroupfs */
1851 dump_frozen_cgroupfs();
Li Li2eedd412021-06-30 15:11:53 -07001852
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001853 if (ds.dump_pool_) {
Aaron Huang24d215d2022-04-27 18:51:16 +08001854 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_netstats_report));
1855 } else {
1856 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_NETSTATS_PROTO_TASK,
1857 DumpNetstatsProto);
1858 }
1859
1860 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001861 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_incident_report));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001862 } else {
1863 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_INCIDENT_REPORT_TASK,
1864 DumpIncidentReport);
1865 }
Mike Ma5c267872019-08-21 11:31:34 -07001866
Kean Mariotti306633e2022-09-05 16:30:47 +00001867 MaybeAddUiTracesToZip();
1868
Nandana Dutt5c390032019-03-12 10:52:56 +00001869 return Dumpstate::RunStatus::OK;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001870}
1871
Nandana Dutt5c390032019-03-12 10:52:56 +00001872/*
1873 * Dumps state for the default case; drops root after it's no longer necessary.
1874 *
1875 * Returns RunStatus::OK if everything went fine.
1876 * Returns RunStatus::ERROR if there was an error.
1877 * Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport
1878 * with the caller.
1879 */
Jichao Lie89d9c12019-11-21 19:02:51 -08001880Dumpstate::RunStatus Dumpstate::DumpstateDefaultAfterCritical() {
Nandana Duttdb379fa2019-10-09 16:54:41 +01001881 // Capture first logcat early on; useful to take a snapshot before dumpstate logs take over the
1882 // buffer.
1883 DoLogcat();
1884 // Capture timestamp after first logcat to use in next logcat
1885 time_t logcat_ts = time(nullptr);
1886
Nandana Dutt4be45d12018-09-26 15:04:23 +01001887 /* collect stack traces from Dalvik and native processes (needs root) */
Chris Morinbc223142022-02-04 14:17:11 -08001888 std::future<std::string> dump_traces;
Rhed Jao5377d792020-07-16 17:37:39 +08001889 if (dump_pool_) {
1890 RETURN_IF_USER_DENIED_CONSENT();
1891 // One thread is enough since we only need to enqueue DumpTraces here.
1892 dump_pool_->start(/* thread_counts = */1);
1893
1894 // DumpTraces takes long time, post it to the another thread in the
1895 // pool, if pool is available
Chris Morinbc223142022-02-04 14:17:11 -08001896 dump_traces = dump_pool_->enqueueTask(
1897 DUMP_TRACES_TASK, &Dumpstate::DumpTraces, &ds, &dump_traces_path);
Rhed Jao5377d792020-07-16 17:37:39 +08001898 } else {
1899 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_TRACES_TASK, ds.DumpTraces,
1900 &dump_traces_path);
1901 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001902
1903 /* Run some operations that require root. */
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001904 if (!PropertiesHelper::IsDryRun()) {
Chris Morinc2cba7a2022-02-01 17:06:50 -08001905 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX);
1906 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX);
Woody Lin20767a92022-11-29 15:50:24 +08001907 ds.shutdown_checkpoints_ = GetDumpFds(
1908 SHUTDOWN_CHECKPOINTS_DIR, SHUTDOWN_CHECKPOINTS_FILE_PREFIX);
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001909 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001910
1911 ds.AddDir(RECOVERY_DIR, true);
1912 ds.AddDir(RECOVERY_DATA_DIR, true);
1913 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
Kelvin Zhang6eaa0f92022-09-12 09:29:19 -07001914 ds.AddDir(UPDATE_ENGINE_PREF_DIR, true);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001915 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1916 if (!PropertiesHelper::IsUserBuild()) {
1917 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1918 ds.AddDir(PROFILE_DATA_DIR_REF, true);
Calin Juravlef84d3692020-04-28 15:31:12 -07001919 ds.AddZipEntry(ZIP_ROOT_DIR + PACKAGE_DEX_USE_LIST, PACKAGE_DEX_USE_LIST);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001920 }
Jerry Changa1df8a92020-01-02 16:03:39 +08001921 ds.AddDir(PREREBOOT_DATA_DIR, false);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001922 add_mountinfo();
Peter Collingbourne78aa2942023-02-15 14:50:31 -08001923 for (const char* path : {"/proc/cpuinfo", "/proc/meminfo"}) {
1924 ds.AddZipEntry(ZIP_ROOT_DIR + path, path);
1925 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001926 DumpIpTablesAsRoot();
David Andersond9ba4752018-12-11 18:26:59 -08001927 DumpDynamicPartitionInfo();
Yifan Hong3945e1b2019-10-29 12:59:23 -07001928 ds.AddDir(OTA_METADATA_DIR, true);
Jeff Sharkey9df29d52023-02-06 14:26:30 -07001929 if (!PropertiesHelper::IsUserBuild()) {
1930 // Include dropbox entry files inside ZIP, but exclude
1931 // noisy WTF and StrictMode entries
1932 dump_files("", DROPBOX_DIR, skip_wtf_strictmode, _add_file_from_fd);
1933 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001934
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001935 // Capture any IPSec policies in play. No keys are exposed here.
Nandana Dutt4be45d12018-09-26 15:04:23 +01001936 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1937
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001938 // Dump IPsec stats. No keys are exposed here.
1939 DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
1940
Nandana Dutt4be45d12018-09-26 15:04:23 +01001941 // Run ss as root so we can see socket marks.
1942 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1943
1944 // Run iotop as root to show top 100 IO threads
1945 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1946
Erick Reyese68df822019-02-11 14:46:36 -08001947 // Gather shared memory buffer info if the product implements it
Hridya Valsaraju1da80c52021-01-09 22:10:11 -08001948 RunCommand("Dmabuf dump", {"dmabuf_dump"});
1949 RunCommand("Dmabuf per-buffer/per-exporter/per-device stats", {"dmabuf_dump", "-b"});
Erick Reyese68df822019-02-11 14:46:36 -08001950
Minchan Kim22c6a1e2019-09-30 15:58:10 -07001951 DumpFile("PSI cpu", "/proc/pressure/cpu");
1952 DumpFile("PSI memory", "/proc/pressure/memory");
1953 DumpFile("PSI io", "/proc/pressure/io");
1954
Mårten Kongstad60195a72022-09-20 14:14:20 +02001955 RunCommand("SDK EXTENSIONS", {SDK_EXT_INFO, "--dump"},
1956 CommandOptions::WithTimeout(10).Always().DropRoot().Build());
1957
Rhed Jao5377d792020-07-16 17:37:39 +08001958 if (dump_pool_) {
1959 RETURN_IF_USER_DENIED_CONSENT();
Chris Morinbc223142022-02-04 14:17:11 -08001960 WaitForTask(std::move(dump_traces));
Rhed Jao5377d792020-07-16 17:37:39 +08001961
Chris Morinbc223142022-02-04 14:17:11 -08001962 // Current running thread in the pool is the root user also. Delete
1963 // the pool and make a new one later to ensure none of threads in the pool are root.
1964 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao5377d792020-07-16 17:37:39 +08001965 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001966 if (!DropRootUser()) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001967 return Dumpstate::RunStatus::ERROR;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001968 }
1969
Nandana Dutt5c390032019-03-12 10:52:56 +00001970 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttdb379fa2019-10-09 16:54:41 +01001971 Dumpstate::RunStatus status = dumpstate();
1972 // Capture logcat since the last time we did it.
1973 DoSystemLogcat(logcat_ts);
1974 return status;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001975}
1976
Rhed Jaob5685b32020-08-14 17:19:17 +08001977// Common states for telephony and wifi which are needed to be collected before
1978// dumpstate drop the root user.
1979static void DumpstateRadioAsRoot() {
1980 DumpIpTablesAsRoot();
1981 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1982}
1983
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001984// This method collects common dumpsys for telephony and wifi. Typically, wifi
1985// reports are fine to include all information, but telephony reports on user
1986// builds need to strip some content (see DumpstateTelephonyOnly).
1987static void DumpstateRadioCommon(bool include_sensitive_info = true) {
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001988 // We need to be picky about some stuff for telephony reports on user builds.
1989 if (!include_sensitive_info) {
1990 // Only dump the radio log buffer (other buffers and dumps contain too much unrelated info).
1991 DoRadioLogcat();
1992 } else {
Rhed Jaob5685b32020-08-14 17:19:17 +08001993 // DumpHals takes long time, post it to the another thread in the pool,
1994 // if pool is available.
Chris Morinbc223142022-02-04 14:17:11 -08001995 std::future<std::string> dump_hals;
Rhed Jaob5685b32020-08-14 17:19:17 +08001996 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001997 dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
Rhed Jaob5685b32020-08-14 17:19:17 +08001998 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001999 // Contains various system properties and process startup info.
2000 do_dmesg();
2001 // Logs other than the radio buffer may contain package/component names and potential PII.
2002 DoLogcat();
2003 // Too broad for connectivity problems.
2004 DoKmsg();
Rhed Jaob5685b32020-08-14 17:19:17 +08002005 // DumpHals contains unrelated hardware info (camera, NFC, biometrics, ...).
2006 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002007 WaitForTask(std::move(dump_hals));
Rhed Jaob5685b32020-08-14 17:19:17 +08002008 } else {
2009 RUN_SLOW_FUNCTION_AND_LOG(DUMP_HALS_TASK, DumpHals);
2010 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002011 }
2012
Jayachandran Ca94c7172017-06-10 15:08:12 -07002013 DumpPacketStats();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002014 DumpIpAddrAndRules();
2015 dump_route_tables();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002016 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
2017 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08002018}
2019
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002020// We use "telephony" here for legacy reasons, though this now really means "connectivity" (cellular
2021// + wifi + networking). This method collects dumpsys for connectivity debugging only. General rules
2022// for what can be included on user builds: all reported information MUST directly relate to
2023// connectivity debugging or customer support and MUST NOT contain unrelated personally identifiable
2024// information. This information MUST NOT identify user-installed packages (UIDs are OK, package
2025// names are not), and MUST NOT contain logs of user application traffic.
2026// TODO(b/148168577) rename this and other related fields/methods to "connectivity" instead.
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08002027static void DumpstateTelephonyOnly(const std::string& calling_package) {
mukesh agrawal253dad42018-01-23 21:59:59 -08002028 DurationReporter duration_reporter("DUMPSTATE");
Jichao Lie89d9c12019-11-21 19:02:51 -08002029
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002030 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
mukesh agrawal253dad42018-01-23 21:59:59 -08002031
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002032 const bool include_sensitive_info = !PropertiesHelper::IsUserBuild();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002033
Rhed Jaob5685b32020-08-14 17:19:17 +08002034 DumpstateRadioAsRoot();
2035 if (!DropRootUser()) {
2036 return;
2037 }
2038
2039 // Starts thread pool after the root user is dropped, and two additional threads
2040 // are created for DumpHals in the DumpstateRadioCommon and DumpstateBoard.
Chris Morinbc223142022-02-04 14:17:11 -08002041 std::future<std::string> dump_board;
Rhed Jaob5685b32020-08-14 17:19:17 +08002042 if (ds.dump_pool_) {
2043 ds.dump_pool_->start(/*thread_counts =*/2);
2044
2045 // DumpstateBoard takes long time, post it to the another thread in the pool,
2046 // if pool is available.
Chris Morinbc223142022-02-04 14:17:11 -08002047 dump_board = ds.dump_pool_->enqueueTaskWithFd(
2048 DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
Rhed Jaob5685b32020-08-14 17:19:17 +08002049 }
2050
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002051 DumpstateRadioCommon(include_sensitive_info);
2052
2053 if (include_sensitive_info) {
2054 // Contains too much unrelated PII, and given the unstructured nature of sysprops, we can't
2055 // really cherrypick all of the connectivity-related ones. Apps generally have no business
2056 // reading these anyway, and there should be APIs to supply the info in a more app-friendly
2057 // way.
2058 RunCommand("SYSTEM PROPERTIES", {"getprop"});
2059 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002060
2061 printf("========================================================\n");
2062 printf("== Android Framework Services\n");
2063 printf("========================================================\n");
2064
Vishnu Nair652cc802017-11-30 15:18:30 -08002065 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2066 SEC_TO_MSEC(10));
Hunter Knepshield31cbae12021-05-11 16:23:24 -07002067 RunDumpsys("DUMPSYS", {"vcn_management"}, CommandOptions::WithTimeout(90).Build(),
2068 SEC_TO_MSEC(10));
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08002069 if (include_sensitive_info) {
2070 // Carrier apps' services will be dumped below in dumpsys activity service all-non-platform.
2071 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
2072 SEC_TO_MSEC(10));
2073 } else {
2074 // If the caller is a carrier app and has a carrier service, dump it here since we aren't
2075 // running dumpsys activity service all-non-platform below. Due to the increased output, we
2076 // give a higher timeout as well.
2077 RunDumpsys("DUMPSYS", {"carrier_config", "--requesting-package", calling_package},
2078 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(30));
2079 }
2080 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002081 RunDumpsys("DUMPSYS", {"netpolicy"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2082 RunDumpsys("DUMPSYS", {"network_management"}, CommandOptions::WithTimeout(90).Build(),
Sooraj Sasindrane8d98912018-04-20 11:31:55 -07002083 SEC_TO_MSEC(10));
Hunter Knepshield0fe51b12020-03-05 16:58:20 -08002084 RunDumpsys("DUMPSYS", {"telephony.registry"}, CommandOptions::WithTimeout(90).Build(),
2085 SEC_TO_MSEC(10));
Jack Yu773cc032023-03-16 22:43:39 -07002086 RunDumpsys("DUMPSYS", {"isub"}, CommandOptions::WithTimeout(90).Build(),
2087 SEC_TO_MSEC(10));
Grant Menke56698972023-02-24 13:11:07 -08002088 RunDumpsys("DUMPSYS", {"telecom"}, CommandOptions::WithTimeout(90).Build(),
2089 SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002090 if (include_sensitive_info) {
2091 // Contains raw IP addresses, omit from reports on user builds.
2092 RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2093 // Contains raw destination IP/MAC addresses, omit from reports on user builds.
2094 RunDumpsys("DUMPSYS", {"connmetrics"}, CommandOptions::WithTimeout(90).Build(),
2095 SEC_TO_MSEC(10));
2096 // Contains package/component names, omit from reports on user builds.
2097 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
2098 SEC_TO_MSEC(10));
2099 // Contains package names, but should be relatively simple to remove them (also contains
2100 // UIDs already), omit from reports on user builds.
2101 RunDumpsys("BATTERYSTATS", {"deviceidle"}, CommandOptions::WithTimeout(90).Build(),
2102 SEC_TO_MSEC(10));
2103 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002104
2105 printf("========================================================\n");
2106 printf("== Running Application Services\n");
2107 printf("========================================================\n");
2108
2109 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
2110
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002111 if (include_sensitive_info) {
2112 printf("========================================================\n");
2113 printf("== Running Application Services (non-platform)\n");
2114 printf("========================================================\n");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002115
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002116 // Contains package/component names and potential PII, omit from reports on user builds.
2117 // To get dumps of the active CarrierService(s) on user builds, we supply an argument to the
2118 // carrier_config dumpsys instead.
2119 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
2120 DUMPSYS_COMPONENTS_OPTIONS);
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002121
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002122 printf("========================================================\n");
2123 printf("== Checkins\n");
2124 printf("========================================================\n");
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002125
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002126 // Contains package/component names, omit from reports on user builds.
2127 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
2128 }
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002129
2130 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07002131 printf("== dumpstate: done (id %d)\n", ds.id_);
2132 printf("========================================================\n");
Rhed Jaob5685b32020-08-14 17:19:17 +08002133
2134 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002135 WaitForTask(std::move(dump_board));
Rhed Jaob5685b32020-08-14 17:19:17 +08002136 } else {
2137 RUN_SLOW_FUNCTION_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
2138 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002139}
2140
mukesh agrawal253dad42018-01-23 21:59:59 -08002141// This method collects dumpsys for wifi debugging only
2142static void DumpstateWifiOnly() {
2143 DurationReporter duration_reporter("DUMPSTATE");
2144
Rhed Jaob5685b32020-08-14 17:19:17 +08002145 DumpstateRadioAsRoot();
2146 if (!DropRootUser()) {
2147 return;
2148 }
2149
2150 // Starts thread pool after the root user is dropped. Only one additional
2151 // thread is needed for DumpHals in the DumpstateRadioCommon.
2152 if (ds.dump_pool_) {
2153 ds.dump_pool_->start(/*thread_counts =*/1);
2154 }
2155
mukesh agrawal253dad42018-01-23 21:59:59 -08002156 DumpstateRadioCommon();
2157
2158 printf("========================================================\n");
2159 printf("== Android Framework Services\n");
2160 printf("========================================================\n");
2161
2162 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2163 SEC_TO_MSEC(10));
2164 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
2165 SEC_TO_MSEC(10));
2166
2167 printf("========================================================\n");
2168 printf("== dumpstate: done (id %d)\n", ds.id_);
2169 printf("========================================================\n");
2170}
2171
Elis Elliott8e401ad2023-08-08 11:18:59 +00002172// Collects a lightweight dumpstate to be used for debugging onboarding related flows.
2173static void DumpstateOnboardingOnly() {
2174 ds.AddDir(LOGPERSIST_DATA_DIR, false);
2175}
2176
Nandana Duttcf419a72019-03-14 10:40:17 +00002177Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
Gavin Corkery789d7a52021-02-24 23:52:35 +00002178 const std::string temp_file_pattern = ds.bugreport_internal_dir_ + "/dumptrace_XXXXXX";
Nandana Duttfaafd522019-03-11 09:23:09 +00002179 const size_t buf_size = temp_file_pattern.length() + 1;
2180 std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
2181 memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
2182
2183 // Create a new, empty file to receive all trace dumps.
2184 //
2185 // TODO: This can be simplified once we remove support for the old style
2186 // dumps. We can have a file descriptor passed in to dump_traces instead
2187 // of creating a file, closing it and then reopening it again.
2188 android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
2189 if (fd < 0) {
2190 MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002191 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002192 }
2193
2194 // Nobody should have access to this temporary file except dumpstate, but we
2195 // temporarily grant 'read' to 'others' here because this file is created
2196 // when tombstoned is still running as root, but dumped after dropping. This
2197 // can go away once support for old style dumping has.
2198 const int chmod_ret = fchmod(fd, 0666);
2199 if (chmod_ret < 0) {
2200 MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002201 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002202 }
2203
2204 std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
2205 if (proc.get() == nullptr) {
2206 MYLOGE("opendir /proc failed: %s\n", strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002207 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002208 }
2209
2210 // Number of times process dumping has timed out. If we encounter too many
2211 // failures, we'll give up.
2212 int timeout_failures = 0;
2213 bool dalvik_found = false;
2214
Jayant Chowdharya0a8eb22022-05-20 03:30:09 +00002215 const std::set<int> hal_pids = get_interesting_pids();
Nandana Duttfaafd522019-03-11 09:23:09 +00002216
2217 struct dirent* d;
2218 while ((d = readdir(proc.get()))) {
Nandana Duttcf419a72019-03-14 10:40:17 +00002219 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttfaafd522019-03-11 09:23:09 +00002220 int pid = atoi(d->d_name);
2221 if (pid <= 0) {
2222 continue;
2223 }
2224
Kevin Jeond0f8a982023-04-07 14:27:11 -04002225 // Skip cached processes.
2226 if (IsCached(pid)) {
2227 // For consistency, the header and footer to this message match those
2228 // dumped by debuggerd in the success case.
2229 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
2230 dprintf(fd, "Dump skipped for cached process.\n");
2231 dprintf(fd, "---- end %d ----", pid);
2232 continue;
2233 }
2234
Nandana Duttfaafd522019-03-11 09:23:09 +00002235 const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
2236 std::string exe;
2237 if (!android::base::Readlink(link_name, &exe)) {
2238 continue;
2239 }
2240
2241 bool is_java_process;
2242 if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
2243 // Don't bother dumping backtraces for the zygote.
2244 if (IsZygote(pid)) {
2245 continue;
2246 }
2247
2248 dalvik_found = true;
2249 is_java_process = true;
2250 } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
2251 is_java_process = false;
2252 } else {
2253 // Probably a native process we don't care about, continue.
2254 continue;
2255 }
2256
2257 // If 3 backtrace dumps fail in a row, consider debuggerd dead.
2258 if (timeout_failures == 3) {
2259 dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
2260 break;
2261 }
2262
2263 const uint64_t start = Nanotime();
2264 const int ret = dump_backtrace_to_file_timeout(
Kevin Jeonb8a39362023-04-04 15:00:34 -04002265 pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace, 3, fd);
Nandana Duttfaafd522019-03-11 09:23:09 +00002266
2267 if (ret == -1) {
2268 // For consistency, the header and footer to this message match those
2269 // dumped by debuggerd in the success case.
2270 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
2271 dprintf(fd, "Dump failed, likely due to a timeout.\n");
2272 dprintf(fd, "---- end %d ----", pid);
2273 timeout_failures++;
2274 continue;
2275 }
2276
2277 // We've successfully dumped stack traces, reset the failure count
2278 // and write a summary of the elapsed time to the file and continue with the
2279 // next process.
2280 timeout_failures = 0;
2281
2282 dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
2283 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
2284 }
2285
2286 if (!dalvik_found) {
2287 MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
2288 }
2289
Nandana Duttcf419a72019-03-14 10:40:17 +00002290 *path = file_name_buf.release();
2291 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002292}
2293
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002294static dumpstate_hal_hidl::DumpstateMode GetDumpstateHalModeHidl(
2295 const Dumpstate::BugreportMode bugreport_mode) {
2296 switch (bugreport_mode) {
2297 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2298 return dumpstate_hal_hidl::DumpstateMode::FULL;
2299 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2300 return dumpstate_hal_hidl::DumpstateMode::INTERACTIVE;
2301 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2302 return dumpstate_hal_hidl::DumpstateMode::REMOTE;
2303 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2304 return dumpstate_hal_hidl::DumpstateMode::WEAR;
2305 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2306 return dumpstate_hal_hidl::DumpstateMode::CONNECTIVITY;
2307 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2308 return dumpstate_hal_hidl::DumpstateMode::WIFI;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002309 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002310 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2311 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2312 }
2313 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2314}
2315
2316static dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode GetDumpstateHalModeAidl(
2317 const Dumpstate::BugreportMode bugreport_mode) {
2318 switch (bugreport_mode) {
2319 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2320 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::FULL;
2321 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2322 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::INTERACTIVE;
2323 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2324 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::REMOTE;
2325 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2326 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WEAR;
2327 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2328 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::CONNECTIVITY;
2329 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2330 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WIFI;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002331 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002332 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2333 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2334 }
2335 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2336}
2337
2338static void DoDumpstateBoardHidl(
2339 const sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_1_0,
2340 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2341 const Dumpstate::BugreportMode bugreport_mode,
2342 const size_t timeout_sec) {
2343
2344 using ScopedNativeHandle =
2345 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
2346 ScopedNativeHandle handle(native_handle_create(static_cast<int>(dumpstate_fds.size()), 0),
2347 [](native_handle_t* handle) {
2348 // we don't close file handle's here
2349 // via native_handle_close(handle)
2350 // instead we let dumpstate_fds close the file handles when
2351 // dumpstate_fds gets destroyed
2352 native_handle_delete(handle);
2353 });
2354 if (handle == nullptr) {
2355 MYLOGE("Could not create native_handle for dumpstate HAL\n");
2356 return;
2357 }
2358
2359 for (size_t i = 0; i < dumpstate_fds.size(); i++) {
2360 handle.get()->data[i] = dumpstate_fds[i].get();
2361 }
2362
2363 // Prefer version 1.1 if available. New devices launching with R are no longer allowed to
2364 // implement just 1.0.
2365 const char* descriptor_to_kill;
2366 using DumpstateBoardTask = std::packaged_task<bool()>;
2367 DumpstateBoardTask dumpstate_board_task;
2368 sp<dumpstate_hal_hidl::IDumpstateDevice> dumpstate_hal(
2369 dumpstate_hal_hidl::IDumpstateDevice::castFrom(dumpstate_hal_1_0));
2370 if (dumpstate_hal != nullptr) {
2371 MYLOGI("Using IDumpstateDevice v1.1 HIDL HAL");
2372
2373 dumpstate_hal_hidl::DumpstateMode dumpstate_hal_mode =
2374 GetDumpstateHalModeHidl(bugreport_mode);
2375
2376 descriptor_to_kill = dumpstate_hal_hidl::IDumpstateDevice::descriptor;
2377 dumpstate_board_task =
2378 DumpstateBoardTask([timeout_sec, dumpstate_hal_mode, dumpstate_hal, &handle]() -> bool {
2379 ::android::hardware::Return<dumpstate_hal_hidl::DumpstateStatus> status =
2380 dumpstate_hal->dumpstateBoard_1_1(handle.get(), dumpstate_hal_mode,
2381 SEC_TO_MSEC(timeout_sec));
2382 if (!status.isOk()) {
2383 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2384 return false;
2385 } else if (status != dumpstate_hal_hidl::DumpstateStatus::OK) {
2386 MYLOGE("dumpstateBoard failed with DumpstateStatus::%s\n",
2387 dumpstate_hal_hidl::toString(status).c_str());
2388 return false;
2389 }
2390 return true;
2391 });
2392 } else {
2393 MYLOGI("Using IDumpstateDevice v1.0 HIDL HAL");
2394
2395 descriptor_to_kill = dumpstate_hal_hidl_1_0::IDumpstateDevice::descriptor;
2396 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal_1_0, &handle]() -> bool {
2397 ::android::hardware::Return<void> status =
2398 dumpstate_hal_1_0->dumpstateBoard(handle.get());
2399 if (!status.isOk()) {
2400 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2401 return false;
2402 }
2403 return true;
2404 });
2405 }
2406 auto result = dumpstate_board_task.get_future();
2407 std::thread(std::move(dumpstate_board_task)).detach();
2408
2409 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2410 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2411 if (!android::base::SetProperty(
2412 "ctl.interface_restart",
2413 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2414 MYLOGE("Couldn't restart dumpstate HAL\n");
2415 }
2416 }
2417 // Wait some time for init to kill dumpstate vendor HAL
2418 constexpr size_t killing_timeout_sec = 10;
2419 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2420 MYLOGE(
2421 "killing dumpstateBoard timed out after %zus, continue and "
2422 "there might be racing in content\n",
2423 killing_timeout_sec);
2424 }
2425}
2426
2427static void DoDumpstateBoardAidl(
2428 const std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal,
2429 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2430 const Dumpstate::BugreportMode bugreport_mode, const size_t timeout_sec) {
2431 MYLOGI("Using IDumpstateDevice AIDL HAL");
2432
2433 const char* descriptor_to_kill;
2434 using DumpstateBoardTask = std::packaged_task<bool()>;
2435 DumpstateBoardTask dumpstate_board_task;
2436 dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode dumpstate_hal_mode =
2437 GetDumpstateHalModeAidl(bugreport_mode);
2438
2439 descriptor_to_kill = dumpstate_hal_aidl::IDumpstateDevice::descriptor;
2440 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal, &dumpstate_fds, dumpstate_hal_mode,
2441 timeout_sec]() -> bool {
2442 auto status = dumpstate_hal->dumpstateBoard(dumpstate_fds, dumpstate_hal_mode, timeout_sec);
2443
2444 if (!status.isOk()) {
2445 MYLOGE("dumpstateBoard failed: %s\n", status.getDescription().c_str());
2446 return false;
2447 }
2448 return true;
2449 });
2450 auto result = dumpstate_board_task.get_future();
2451 std::thread(std::move(dumpstate_board_task)).detach();
2452
2453 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2454 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2455 if (!android::base::SetProperty(
2456 "ctl.interface_restart",
2457 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2458 MYLOGE("Couldn't restart dumpstate HAL\n");
2459 }
2460 }
2461 // Wait some time for init to kill dumpstate vendor HAL
2462 constexpr size_t killing_timeout_sec = 10;
2463 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2464 MYLOGE(
2465 "killing dumpstateBoard timed out after %zus, continue and "
2466 "there might be racing in content\n",
2467 killing_timeout_sec);
2468 }
2469}
2470
2471static std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> GetDumpstateBoardAidlService() {
2472 const std::string aidl_instance_name =
2473 std::string(dumpstate_hal_aidl::IDumpstateDevice::descriptor) + "/default";
2474
2475 if (!AServiceManager_isDeclared(aidl_instance_name.c_str())) {
2476 return nullptr;
2477 }
2478
2479 ndk::SpAIBinder dumpstateBinder(AServiceManager_waitForService(aidl_instance_name.c_str()));
2480
2481 return dumpstate_hal_aidl::IDumpstateDevice::fromBinder(dumpstateBinder);
2482}
2483
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002484void Dumpstate::DumpstateBoard(int out_fd) {
2485 dprintf(out_fd, "========================================================\n");
2486 dprintf(out_fd, "== Board\n");
2487 dprintf(out_fd, "========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08002488
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002489 /*
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002490 * mount debugfs for non-user builds with ro.product.debugfs_restrictions.enabled
Hridya Valsaraju51101602021-04-02 14:32:46 -07002491 * set to true and unmount it after invoking dumpstateBoard_* methods.
2492 * This is to enable debug builds to not have debugfs mounted during runtime.
2493 * It will also ensure that debugfs is only accessed by the dumpstate HAL.
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002494 */
Hridya Valsaraju51101602021-04-02 14:32:46 -07002495 auto mount_debugfs =
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002496 android::base::GetBoolProperty("ro.product.debugfs_restrictions.enabled", false);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002497 if (mount_debugfs) {
2498 RunCommand("mount debugfs", {"mount", "-t", "debugfs", "debugfs", "/sys/kernel/debug"},
2499 AS_ROOT_20);
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002500 RunCommand("chmod debugfs", {"chmod", "0755", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002501 }
2502
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002503 std::vector<std::string> paths;
2504 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07002505 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002506 paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
2507 kDumpstateBoardFiles[i].c_str()));
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002508 remover.emplace_back(android::base::make_scope_guard(
2509 std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002510 }
Jie Song9fbfad02017-06-20 16:29:42 -07002511
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002512 // get dumpstate HAL AIDL implementation
2513 std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal_handle_aidl(
2514 GetDumpstateBoardAidlService());
2515 if (dumpstate_hal_handle_aidl == nullptr) {
2516 MYLOGI("No IDumpstateDevice AIDL implementation\n");
2517 }
2518
2519 // get dumpstate HAL HIDL implementation, only if AIDL HAL implementation not found
2520 sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_handle_hidl_1_0 = nullptr;
2521 if (dumpstate_hal_handle_aidl == nullptr) {
2522 dumpstate_hal_handle_hidl_1_0 = dumpstate_hal_hidl_1_0::IDumpstateDevice::getService();
2523 if (dumpstate_hal_handle_hidl_1_0 == nullptr) {
2524 MYLOGI("No IDumpstateDevice HIDL implementation\n");
2525 }
2526 }
2527
2528 // if neither HIDL nor AIDL implementation found, then return
2529 if (dumpstate_hal_handle_hidl_1_0 == nullptr && dumpstate_hal_handle_aidl == nullptr) {
2530 MYLOGE("Could not find IDumpstateDevice implementation\n");
Wei Wang587eac92018-04-05 12:17:20 -07002531 return;
2532 }
2533
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002534 // this is used to hold the file descriptors and when this variable goes out of scope
2535 // the file descriptors are closed
2536 std::vector<::ndk::ScopedFileDescriptor> dumpstate_fds;
Wei Wang587eac92018-04-05 12:17:20 -07002537
Nandana Dutt5c390032019-03-12 10:52:56 +00002538 // TODO(128270426): Check for consent in between?
Wei Wang587eac92018-04-05 12:17:20 -07002539 for (size_t i = 0; i < paths.size(); i++) {
2540 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
2541
2542 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
2543 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
2544 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
2545 if (fd < 0) {
2546 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
2547 return;
2548 }
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002549
2550 dumpstate_fds.emplace_back(fd.release());
2551 // we call fd.release() here to make sure "fd" does not get closed
2552 // after "fd" goes out of scope after this block.
2553 // "fd" will be closed when "dumpstate_fds" goes out of scope
2554 // i.e. when we exit this function
Wei Wang587eac92018-04-05 12:17:20 -07002555 }
2556
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002557 // Given that bugreport is required to diagnose failures, it's better to set an arbitrary amount
2558 // of timeout for IDumpstateDevice than to block the rest of bugreport. In the timeout case, we
2559 // will kill the HAL and grab whatever it dumped in time.
Michael Eastwood8523ea02022-03-10 16:33:08 -08002560 constexpr size_t timeout_sec = 45;
Wei Wang587eac92018-04-05 12:17:20 -07002561
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002562 if (dumpstate_hal_handle_aidl != nullptr) {
2563 DoDumpstateBoardAidl(dumpstate_hal_handle_aidl, dumpstate_fds, options_->bugreport_mode,
2564 timeout_sec);
2565 } else if (dumpstate_hal_handle_hidl_1_0 != nullptr) {
2566 // run HIDL HAL only if AIDL HAL not found
2567 DoDumpstateBoardHidl(dumpstate_hal_handle_hidl_1_0, dumpstate_fds, options_->bugreport_mode,
2568 timeout_sec);
Wei Wang587eac92018-04-05 12:17:20 -07002569 }
2570
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002571 if (mount_debugfs) {
Hridya Valsaraju51101602021-04-02 14:32:46 -07002572 auto keep_debugfs_mounted =
2573 android::base::GetProperty("persist.dbg.keep_debugfs_mounted", "");
2574 if (keep_debugfs_mounted.empty())
2575 RunCommand("unmount debugfs", {"umount", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002576 }
2577
Wei Wang587eac92018-04-05 12:17:20 -07002578 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
2579 for (size_t i = 0; i < paths.size(); i++) {
2580 struct stat s;
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002581 if (fstat(dumpstate_fds[i].get(), &s) == -1) {
2582 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(), strerror(errno));
Wei Wang587eac92018-04-05 12:17:20 -07002583 file_sizes[i] = -1;
2584 continue;
2585 }
2586 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002587 }
2588
2589 for (size_t i = 0; i < paths.size(); i++) {
2590 if (file_sizes[i] == -1) {
2591 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002592 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002593 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07002594 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002595 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002596 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002597 remover[i].Disable();
2598 EnqueueAddZipEntryAndCleanupIfNeeded(kDumpstateBoardFiles[i], paths[i]);
2599 dprintf(out_fd, "*** See %s entry ***\n", kDumpstateBoardFiles[i].c_str());
Jie Song9fbfad02017-06-20 16:29:42 -07002600 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08002601}
2602
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002603static void ShowUsage() {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002604 fprintf(stderr,
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002605 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o directory] [-p] "
2606 "[-s] [-S] [-q] [-P] [-R] [-L] [-V version]\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002607 " -h: display this help message\n"
2608 " -b: play sound file instead of vibrate, at beginning of job\n"
2609 " -e: play sound file instead of vibrate, at end of job\n"
mhasank2d75c442020-06-11 15:05:25 -07002610 " -o: write to custom directory (only in limited mode)\n"
Abhijeet Kaurbb55a3b2019-06-13 18:07:25 +01002611 " -p: capture screenshot to filename.png\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002612 " -s: write zipped file to control socket (for init)\n"
2613 " -S: write file location to control socket (for init)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002614 " -q: disable vibrate\n"
Abhijeet Kaure370d682019-10-01 16:49:30 +01002615 " -P: send broadcast when started and do progress updates\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002616 " -R: take bugreport in remote mode (shouldn't be used with -P)\n"
Nandana Dutt235864b2019-01-22 12:10:16 +00002617 " -w: start binder service and make it wait for a call to startBugreport\n"
mhasankd451a472020-05-26 18:02:39 -07002618 " -L: output limited information that is safe for submission in feedback reports\n"
Felipe Lemed071c682016-10-20 16:48:00 -07002619 " -v: prints the dumpstate header and exit\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002620}
2621
Wei Liuf87959e2016-08-26 14:51:42 -07002622static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07002623 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07002624}
2625
Felipe Leme1d486fe2016-10-14 18:06:47 -07002626bool Dumpstate::FinishZipFile() {
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002627 // Runs all enqueued adding zip entry and cleanup tasks before finishing the zip file.
2628 if (zip_entry_tasks_) {
2629 zip_entry_tasks_->run(/* do_cancel = */false);
2630 }
2631
Felipe Leme9a523ae2016-10-20 15:10:33 -07002632 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07002633 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07002634 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002635 // Final timestamp
2636 char date[80];
2637 time_t the_real_now_please_stand_up = time(nullptr);
2638 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002639 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002640 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002641
Felipe Leme9a523ae2016-10-20 15:10:33 -07002642 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002643 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08002644 return false;
2645 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07002646 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002647 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08002648 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08002649 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08002650
Felipe Leme0f3fb202016-06-10 17:10:53 -07002651 // Add log file (which contains stderr output) to zip...
2652 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002653 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07002654 MYLOGE("Failed to add dumpstate log to .zip file\n");
2655 return false;
2656 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002657 // TODO: Should truncate the existing file.
2658 // ... and re-open it for further logging.
Nandana Dutta344cb62019-02-22 15:12:35 +00002659 if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
2660 return false;
2661 }
Felipe Leme0f3fb202016-06-10 17:10:53 -07002662 fprintf(stderr, "\n");
2663
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002664 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07002665 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002666 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002667 return false;
2668 }
2669
Felipe Leme1d486fe2016-10-14 18:06:47 -07002670 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
2671 ds.zip_file.reset(nullptr);
2672
Felipe Lemee9d2c542016-11-15 11:48:26 -08002673 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002674 android::os::UnlinkAndLogOnError(tmp_path_);
Felipe Lemec4eee562016-04-21 15:42:55 -07002675
Felipe Leme1e9edc62015-12-21 16:02:13 -08002676 return true;
2677}
Felipe Leme6e01fa62015-11-11 19:35:14 -08002678
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00002679static void SendBroadcast(const std::string& action,
2680 const std::vector<std::string>& args,
2681 int32_t user_id) {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002682 // clang-format off
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00002683 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user",
2684 std::to_string(user_id), "--receiver-foreground",
2685 "--receiver-include-background", "-a", action};
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002686 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08002687
2688 am.insert(am.end(), args.begin(), args.end());
2689
Felipe Leme8d2410e2017-02-08 09:46:08 -08002690 RunCommand("", am,
2691 CommandOptions::WithTimeout(20)
2692 .Log("Sending broadcast: '%s'\n")
2693 .Always()
2694 .DropRoot()
2695 .RedirectStderr()
2696 .Build());
2697}
2698
Felipe Leme35b8cf12017-02-10 15:47:29 -08002699static void Vibrate(int duration_ms) {
2700 // clang-format off
Lais Andrade51156962021-02-22 19:21:35 +00002701 std::vector<std::string> args = {"cmd", "vibrator_manager", "synced", "-f", "-d", "dumpstate",
2702 "oneshot", std::to_string(duration_ms)};
2703 RunCommand("", args,
Felipe Leme35b8cf12017-02-10 15:47:29 -08002704 CommandOptions::WithTimeout(10)
2705 .Log("Vibrate: '%s'\n")
2706 .Always()
2707 .Build());
2708 // clang-format on
2709}
2710
Nandana Dutt979388e2018-11-30 16:48:55 +00002711static void MaybeResolveSymlink(std::string* path) {
2712 std::string resolved_path;
2713 if (android::base::Readlink(*path, &resolved_path)) {
2714 *path = resolved_path;
2715 }
2716}
2717
Nandana Dutt4be45d12018-09-26 15:04:23 +01002718/*
2719 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002720 * and adds the version file. Return false if zip_file could not be open to write.
Nandana Dutt4be45d12018-09-26 15:04:23 +01002721 */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002722static bool PrepareToWriteToFile() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002723 MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2724
Nandana Dutt4be45d12018-09-26 15:04:23 +01002725 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2726 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002727 ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002728 char date[80];
2729 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2730 ds.name_ = date;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002731
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002732 if (ds.options_->telephony_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002733 ds.base_name_ += "-telephony";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002734 } else if (ds.options_->wifi_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002735 ds.base_name_ += "-wifi";
2736 }
2737
Paul Chang0d2aad72020-02-13 20:04:03 +08002738 if (ds.options_->do_screenshot) {
Nandana Dutt9d17b942020-03-26 10:02:59 +00002739 ds.screenshot_path_ = ds.GetPath(ds.CalledByApi() ? "-png.tmp" : ".png");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002740 }
2741 ds.tmp_path_ = ds.GetPath(".tmp");
2742 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2743
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01002744 std::string destination = ds.CalledByApi()
Nandana Dutt54dbd672019-01-11 12:58:05 +00002745 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
Nandana Dutt9a76d202019-01-21 15:56:48 +00002746 : ds.bugreport_internal_dir_.c_str();
Nandana Dutt4be45d12018-09-26 15:04:23 +01002747 MYLOGD(
Nandana Dutt235c6672019-11-14 15:22:32 +00002748 "Bugreport dir: [%s] "
2749 "Base name: [%s] "
2750 "Suffix: [%s] "
2751 "Log path: [%s] "
2752 "Temporary path: [%s] "
2753 "Screenshot path: [%s]\n",
Nandana Dutt9a76d202019-01-21 15:56:48 +00002754 destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2755 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002756
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002757 ds.path_ = ds.GetPath(ds.CalledByApi() ? "-zip.tmp" : ".zip");
2758 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2759 create_parent_dirs(ds.path_.c_str());
2760 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2761 if (ds.zip_file == nullptr) {
2762 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2763 return false;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002764 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002765 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2766 ds.AddTextZipEntry("version.txt", ds.version_);
2767 return true;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002768}
2769
2770/*
Abhijeet Kaure370d682019-10-01 16:49:30 +01002771 * Finalizes writing to the file by zipping the tmp file to the final location,
Nandana Dutt4be45d12018-09-26 15:04:23 +01002772 * printing zipped file status, etc.
2773 */
2774static void FinalizeFile() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002775 bool do_text_file = !ds.FinishZipFile();
2776 if (do_text_file) {
2777 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002778 }
mhasank2d75c442020-06-11 15:05:25 -07002779
2780 std::string final_path = ds.path_;
2781 if (ds.options_->OutputToCustomFile()) {
mhasank3a4cfb42020-06-15 18:06:43 -07002782 final_path = ds.GetPath(ds.options_->out_dir, ".zip");
mhasank2d75c442020-06-11 15:05:25 -07002783 android::os::CopyFileToFile(ds.path_, final_path);
2784 }
2785
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002786 if (ds.options_->stream_to_socket) {
2787 android::os::CopyFileToFd(ds.path_, ds.control_socket_fd_);
2788 } else if (ds.options_->progress_updates_to_socket) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002789 if (do_text_file) {
2790 dprintf(ds.control_socket_fd_,
2791 "FAIL:could not create zip file, check %s "
2792 "for more details\n",
2793 ds.log_path_.c_str());
2794 } else {
mhasank2d75c442020-06-11 15:05:25 -07002795 dprintf(ds.control_socket_fd_, "OK:%s\n", final_path.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002796 }
2797 }
2798}
2799
Nandana Dutt4be45d12018-09-26 15:04:23 +01002800
Nandana Dutt58d72e22018-11-16 10:30:48 +00002801static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2802 switch (mode) {
2803 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2804 return "BUGREPORT_FULL";
2805 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2806 return "BUGREPORT_INTERACTIVE";
2807 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2808 return "BUGREPORT_REMOTE";
2809 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2810 return "BUGREPORT_WEAR";
2811 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2812 return "BUGREPORT_TELEPHONY";
2813 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2814 return "BUGREPORT_WIFI";
Elis Elliott8e401ad2023-08-08 11:18:59 +00002815 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
2816 return "BUGREPORT_ONBOARDING";
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002817 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2818 return "BUGREPORT_DEFAULT";
Nandana Dutt58d72e22018-11-16 10:30:48 +00002819 }
2820}
2821
Steven Leeb573eb82022-11-29 22:31:35 +08002822static bool IsConsentlessBugreportAllowed(const Dumpstate::DumpOptions& options) {
2823 // only BUGREPORT_TELEPHONY does not allow using consentless bugreport
2824 return !options.telephony_only;
2825}
2826
Paul Changf59c2b72020-03-10 02:08:55 +08002827static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options,
2828 bool is_screenshot_requested) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002829 // Modify com.android.shell.BugreportProgressService#isDefaultScreenshotRequired as well for
2830 // default system screenshots.
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002831 options->bugreport_mode = mode;
2832 options->bugreport_mode_string = ModeToString(mode);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002833 switch (mode) {
2834 case Dumpstate::BugreportMode::BUGREPORT_FULL:
Paul Changf59c2b72020-03-10 02:08:55 +08002835 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002836 break;
2837 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002838 // Currently, the dumpstate binder is only used by Shell to update progress.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002839 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002840 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002841 break;
2842 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002843 options->do_vibrate = false;
2844 options->is_remote_mode = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002845 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002846 break;
2847 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
Robert Ginda55ecebd2023-04-03 22:53:13 +00002848 options->do_vibrate = false;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002849 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002850 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002851 break;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002852 // TODO(b/148168577) rename TELEPHONY everywhere to CONNECTIVITY.
Nandana Dutt58d72e22018-11-16 10:30:48 +00002853 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002854 options->telephony_only = true;
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002855 options->do_progress_updates = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002856 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002857 break;
2858 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002859 options->wifi_only = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002860 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002861 break;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002862 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
2863 options->onboarding_only = true;
2864 options->do_screenshot = false;
2865 break;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002866 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2867 break;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002868 }
2869}
2870
Nandana Dutt58d72e22018-11-16 10:30:48 +00002871static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
Nandana Dutt235c6672019-11-14 15:22:32 +00002872 MYLOGI(
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002873 "do_vibrate: %d stream_to_socket: %d progress_updates_to_socket: %d do_screenshot: %d "
Rhed Jao25f50e02020-08-20 00:10:32 +08002874 "is_remote_mode: %d show_header_only: %d telephony_only: %d "
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002875 "wifi_only: %d do_progress_updates: %d fd: %d bugreport_mode: %s "
mhasankd451a472020-05-26 18:02:39 -07002876 "limited_only: %d args: %s\n",
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002877 options.do_vibrate, options.stream_to_socket, options.progress_updates_to_socket,
Paul Chang0d2aad72020-02-13 20:04:03 +08002878 options.do_screenshot, options.is_remote_mode, options.show_header_only,
Rhed Jao25f50e02020-08-20 00:10:32 +08002879 options.telephony_only, options.wifi_only,
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002880 options.do_progress_updates, options.bugreport_fd.get(),
2881 options.bugreport_mode_string.c_str(),
2882 options.limited_only, options.args.c_str());
Nandana Dutt58d72e22018-11-16 10:30:48 +00002883}
2884
Nandana Dutt54dbd672019-01-11 12:58:05 +00002885void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
Kean Mariotti306633e2022-09-05 16:30:47 +00002886 int bugreport_flags,
Nandana Dutt54dbd672019-01-11 12:58:05 +00002887 const android::base::unique_fd& bugreport_fd_in,
Paul Changf59c2b72020-03-10 02:08:55 +08002888 const android::base::unique_fd& screenshot_fd_in,
2889 bool is_screenshot_requested) {
Kean Mariotti306633e2022-09-05 16:30:47 +00002890 this->use_predumped_ui_data = bugreport_flags & BugreportFlag::BUGREPORT_USE_PREDUMPED_UI_DATA;
Gavin Corkerya44686c2022-11-23 18:16:51 +00002891 this->is_consent_deferred = bugreport_flags & BugreportFlag::BUGREPORT_FLAG_DEFER_CONSENT;
Nandana Dutt54dbd672019-01-11 12:58:05 +00002892 // Duplicate the fds because the passed in fds don't outlive the binder transaction.
Todd Frederick621533f2022-03-26 02:54:17 +00002893 bugreport_fd.reset(fcntl(bugreport_fd_in.get(), F_DUPFD_CLOEXEC, 0));
2894 screenshot_fd.reset(fcntl(screenshot_fd_in.get(), F_DUPFD_CLOEXEC, 0));
Nandana Dutt58d72e22018-11-16 10:30:48 +00002895
Paul Changf59c2b72020-03-10 02:08:55 +08002896 SetOptionsFromMode(bugreport_mode, this, is_screenshot_requested);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002897}
2898
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002899Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
2900 RunStatus status = RunStatus::OK;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002901 int c;
mhasankd451a472020-05-26 18:02:39 -07002902 while ((c = getopt(argc, argv, "dho:svqzpLPBRSV:w")) != -1) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002903 switch (c) {
2904 // clang-format off
mhasank3a4cfb42020-06-15 18:06:43 -07002905 case 'o': out_dir = optarg; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002906 case 's': stream_to_socket = true; break;
2907 case 'S': progress_updates_to_socket = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002908 case 'v': show_header_only = true; break;
2909 case 'q': do_vibrate = false; break;
Paul Chang0d2aad72020-02-13 20:04:03 +08002910 case 'p': do_screenshot = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002911 case 'P': do_progress_updates = true; break;
2912 case 'R': is_remote_mode = true; break;
mhasankd451a472020-05-26 18:02:39 -07002913 case 'L': limited_only = true; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002914 case 'V':
2915 case 'd':
2916 case 'z':
2917 // compatibility no-op
2918 break;
Nandana Dutt235864b2019-01-22 12:10:16 +00002919 case 'w':
2920 // This was already processed
2921 break;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002922 case 'h':
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002923 status = RunStatus::HELP;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002924 break;
2925 default:
2926 fprintf(stderr, "Invalid option: %c\n", c);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002927 status = RunStatus::INVALID_INPUT;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002928 break;
2929 // clang-format on
2930 }
2931 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08002932
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002933 for (int i = 0; i < argc; i++) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002934 args += argv[i];
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002935 if (i < argc - 1) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002936 args += " ";
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002937 }
2938 }
2939
2940 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
2941 optind = 1;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002942
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002943 return status;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002944}
2945
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002946bool Dumpstate::DumpOptions::ValidateOptions() const {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002947 if (bugreport_fd.get() != -1 && stream_to_socket) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002948 return false;
2949 }
2950
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002951 if ((progress_updates_to_socket || do_progress_updates) && stream_to_socket) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002952 return false;
2953 }
2954
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002955 if (is_remote_mode && (do_progress_updates || stream_to_socket)) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002956 return false;
2957 }
2958 return true;
2959}
2960
Nandana Dutt197661d2018-11-16 16:40:21 +00002961void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
2962 options_ = std::move(options);
2963}
2964
Abhijeet Kaura407fb82020-03-27 12:51:12 +00002965void Dumpstate::Initialize() {
2966 /* gets the sequential id */
2967 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
2968 id_ = ++last_id;
2969 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
2970}
2971
Nandana Duttd2f5f082019-01-18 17:13:52 +00002972Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
2973 Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
Gavin Corkerya44686c2022-11-23 18:16:51 +00002974 HandleRunStatus(status);
2975 return status;
2976}
2977
2978Dumpstate::RunStatus Dumpstate::Retrieve(int32_t calling_uid, const std::string& calling_package) {
2979 Dumpstate::RunStatus status = RetrieveInternal(calling_uid, calling_package);
2980 HandleRunStatus(status);
2981 return status;
2982}
2983
2984Dumpstate::RunStatus Dumpstate::RetrieveInternal(int32_t calling_uid,
2985 const std::string& calling_package) {
2986 consent_callback_ = new ConsentCallback();
2987 const String16 incidentcompanion("incidentcompanion");
2988 sp<android::IBinder> ics(
2989 defaultServiceManager()->checkService(incidentcompanion));
2990 android::String16 package(calling_package.c_str());
2991 if (ics != nullptr) {
2992 MYLOGD("Checking user consent via incidentcompanion service\n");
2993 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
2994 calling_uid, package, String16(), String16(),
2995 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
2996 } else {
2997 MYLOGD(
2998 "Unable to check user consent; incidentcompanion service unavailable\n");
2999 return RunStatus::USER_CONSENT_TIMED_OUT;
3000 }
3001 UserConsentResult consent_result = consent_callback_->getResult();
3002 int timeout_ms = 30 * 1000;
3003 while (consent_result == UserConsentResult::UNAVAILABLE &&
3004 consent_callback_->getElapsedTimeMs() < timeout_ms) {
3005 sleep(1);
3006 consent_result = consent_callback_->getResult();
3007 }
3008 if (consent_result == UserConsentResult::DENIED) {
3009 return RunStatus::USER_CONSENT_DENIED;
3010 }
3011 if (consent_result == UserConsentResult::UNAVAILABLE) {
3012 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3013 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3014 consent_callback_.get());
3015 return RunStatus::USER_CONSENT_TIMED_OUT;
3016 }
3017
3018 bool copy_succeeded =
3019 android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
3020 if (copy_succeeded) {
3021 android::os::UnlinkAndLogOnError(path_);
3022 }
3023 return copy_succeeded ? Dumpstate::RunStatus::OK
3024 : Dumpstate::RunStatus::ERROR;
3025}
3026
3027void Dumpstate::HandleRunStatus(Dumpstate::RunStatus status) {
3028 if (listener_ != nullptr) {
Nandana Duttbabf6c72019-01-15 14:11:12 +00003029 switch (status) {
3030 case Dumpstate::RunStatus::OK:
Gavin Corkerya44686c2022-11-23 18:16:51 +00003031 listener_->onFinished(path_.c_str());
Nandana Duttbabf6c72019-01-15 14:11:12 +00003032 break;
3033 case Dumpstate::RunStatus::HELP:
3034 break;
3035 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003036 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00003037 break;
3038 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003039 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
3040 break;
3041 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3042 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
3043 break;
3044 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
3045 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00003046 break;
3047 }
3048 }
Nandana Duttbabf6c72019-01-15 14:11:12 +00003049}
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003050void Dumpstate::Cancel() {
3051 CleanupTmpFiles();
3052 android::os::UnlinkAndLogOnError(log_path_);
3053 for (int i = 0; i < NUM_OF_DUMPS; i++) {
3054 android::os::UnlinkAndLogOnError(ds.bugreport_internal_dir_ + "/" +
3055 kDumpstateBoardFiles[i]);
3056 }
3057 tombstone_data_.clear();
3058 anr_data_.clear();
Woody Lin20767a92022-11-29 15:50:24 +08003059 shutdown_checkpoints_.clear();
Rhed Jao0daac912020-08-21 14:48:20 +08003060
3061 // Instead of shutdown the pool, we delete temporary files directly since
3062 // shutdown blocking the call.
3063 if (dump_pool_) {
3064 dump_pool_->deleteTempFiles();
3065 }
3066 if (zip_entry_tasks_) {
3067 zip_entry_tasks_->run(/*do_cancel =*/ true);
3068 }
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003069}
3070
Kean Mariotti306633e2022-09-05 16:30:47 +00003071void Dumpstate::PreDumpUiData() {
Kean Mariotti853b73a2023-07-27 12:40:30 +00003072 MaybeSnapshotSystemTrace();
Kean Mariotti306633e2022-09-05 16:30:47 +00003073 MaybeSnapshotUiTraces();
3074}
3075
Nandana Dutt979388e2018-11-30 16:48:55 +00003076/*
3077 * Dumps relevant information to a bugreport based on the given options.
3078 *
3079 * The bugreport can be dumped to a file or streamed to a socket.
3080 *
3081 * How dumping to file works:
3082 * stdout is redirected to a temporary file. This will later become the main bugreport entry.
3083 * stderr is redirected a log file.
3084 *
3085 * The temporary bugreport is then populated via printfs, dumping contents of files and
3086 * output of commands to stdout.
3087 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003088 * A bunch of other files and dumps are added to the zip archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00003089 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003090 * The temporary bugreport file and the log file also get added to the archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00003091 *
mhasank2d75c442020-06-11 15:05:25 -07003092 * Bugreports are first generated in a local directory and later copied to the caller's fd
3093 * or directory if supplied.
Nandana Dutt979388e2018-11-30 16:48:55 +00003094 */
Nandana Duttd2f5f082019-01-18 17:13:52 +00003095Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
3096 const std::string& calling_package) {
Rhed Jao5377d792020-07-16 17:37:39 +08003097 DurationReporter duration_reporter("RUN INTERNAL", /* logcat_only = */true);
Nandana Dutt979388e2018-11-30 16:48:55 +00003098 LogDumpOptions(*options_);
Nandana Dutt197661d2018-11-16 16:40:21 +00003099 if (!options_->ValidateOptions()) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00003100 MYLOGE("Invalid options specified\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003101 return RunStatus::INVALID_INPUT;
3102 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003103 /* set as high priority, and protect from OOM killer */
3104 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003105
Felipe Lemed071c682016-10-20 16:48:00 -07003106 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07003107 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003108 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003109 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003110 } else {
3111 /* fallback to kernels <= 2.6.35 */
3112 oom_adj = fopen("/proc/self/oom_adj", "we");
3113 if (oom_adj) {
3114 fputs("-17", oom_adj);
3115 fclose(oom_adj);
3116 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003117 }
3118
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003119 if (version_ == VERSION_DEFAULT) {
3120 version_ = VERSION_CURRENT;
Michal Karpinski4db754f2015-12-11 18:04:32 +00003121 }
3122
Chris Morin5a50d482022-02-01 17:41:18 -08003123 if (version_ != VERSION_CURRENT) {
3124 MYLOGE("invalid version requested ('%s'); supported values are: ('%s', '%s')\n",
3125 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003126 return RunStatus::INVALID_INPUT;
Felipe Lemed071c682016-10-20 16:48:00 -07003127 }
3128
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003129 if (options_->show_header_only) {
3130 PrintHeader();
3131 return RunStatus::OK;
Felipe Lemed071c682016-10-20 16:48:00 -07003132 }
3133
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003134 MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n",
3135 calling_uid, calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003136
Felipe Leme7447d7c2016-11-03 18:12:22 -07003137 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003138 std::string stats_path =
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003139 android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003140 progress_.reset(new Progress(stats_path));
Felipe Leme7447d7c2016-11-03 18:12:22 -07003141
Sahana Raof35ed432019-07-12 10:47:52 +01003142 if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
3143 MYLOGE("Failed to acquire wake lock: %s\n", strerror(errno));
3144 } else {
3145 // Wake lock will be released automatically on process death
3146 MYLOGD("Wake lock acquired.\n");
3147 }
3148
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08003149 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07003150
Felipe Lemef0292972016-11-22 13:57:05 -08003151 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07003152 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
3153 }
3154
Kevin Jeonfa64e642023-07-27 11:36:41 -04003155 if (PropertiesHelper::IsStrictRun()) {
3156 MYLOGI(
3157 "Running on strict-run mode, which has shorter timeouts "
3158 "(to disable, call 'setprop dumpstate.strict_run false')\n");
3159 }
3160
Nandana Dutt235c6672019-11-14 15:22:32 +00003161 MYLOGI("dumpstate info: id=%d, args='%s', bugreport_mode= %s bugreport format version: %s\n",
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00003162 id_, options_->args.c_str(), options_->bugreport_mode_string.c_str(), version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08003163
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003164 do_early_screenshot_ = options_->do_progress_updates;
Felipe Lemee338bf62015-12-07 14:03:50 -08003165
Christopher Ferrised9354f2014-10-01 17:35:01 -07003166 // If we are going to use a socket, do it as early as possible
3167 // to avoid timeouts from bugreport.
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003168 if (options_->stream_to_socket || options_->progress_updates_to_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07003169 MYLOGD("Opening control socket\n");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003170 control_socket_fd_ = open_socket_fn_("dumpstate");
Nandana Dutta344cb62019-02-22 15:12:35 +00003171 if (control_socket_fd_ == -1) {
3172 return ERROR;
3173 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003174 if (options_->progress_updates_to_socket) {
3175 options_->do_progress_updates = 1;
3176 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07003177 }
3178
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003179 if (!PrepareToWriteToFile()) {
3180 return ERROR;
3181 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08003182
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003183 // Interactive, wear & telephony modes are default to true.
3184 // and may enable from cli option or when using control socket
3185 if (options_->do_progress_updates) {
3186 // clang-format off
3187 std::vector<std::string> am_args = {
3188 "--receiver-permission", "android.permission.DUMP",
3189 };
3190 // clang-format on
3191 // Send STARTED broadcast for apps that listen to bugreport generation events
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003192 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED",
3193 am_args, multiuser_get_user_id(calling_uid));
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003194 if (options_->progress_updates_to_socket) {
3195 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08003196 }
3197 }
3198
Nick Kralevichf3599b32016-01-25 15:05:16 -08003199 /* read /proc/cmdline before dropping root */
3200 FILE *cmdline = fopen("/proc/cmdline", "re");
3201 if (cmdline) {
3202 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
3203 fclose(cmdline);
3204 }
3205
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003206 if (options_->do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08003207 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05003208 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003209
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003210 if (zip_file != nullptr) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003211 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
3212 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003213 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08003214 }
3215 }
3216
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003217 int dup_stdout_fd;
3218 int dup_stderr_fd;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003219 // Redirect stderr to log_path_ for debugging.
3220 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
3221 if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
3222 return ERROR;
3223 }
3224 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
3225 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
3226 strerror(errno));
3227 }
Nandana Dutt979388e2018-11-30 16:48:55 +00003228
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003229 // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
3230 // moved into zip file later, if zipping.
3231 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
3232 // TODO: why not write to a file instead of stdout to overcome this problem?
3233 /* TODO: rather than generating a text file now and zipping it later,
3234 it would be more efficient to redirect stdout to the zip entry
3235 directly, but the libziparchive doesn't support that option yet. */
3236 if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
3237 return ERROR;
3238 }
3239 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
3240 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
3241 tmp_path_.c_str(), strerror(errno));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003242 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08003243
3244 // Don't buffer stdout
3245 setvbuf(stdout, nullptr, _IONBF, 0);
3246
Rhed Jao5377d792020-07-16 17:37:39 +08003247 // Enable the parallel run if the client requests to output to a file.
3248 EnableParallelRunIfNeeded();
3249 // Using scope guard to make sure the dump pool can be shut down correctly.
3250 auto scope_guard_to_shutdown_pool = android::base::make_scope_guard([=]() {
3251 ShutdownDumpPool();
3252 });
3253
Felipe Leme608385d2016-02-01 10:35:38 -08003254 // NOTE: there should be no stdout output until now, otherwise it would break the header.
3255 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08003256 // duration is logged into MYLOG instead.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003257 PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003258
Kean Mariotti853b73a2023-07-27 12:40:30 +00003259 bool is_dumpstate_restricted =
3260 options_->telephony_only || options_->wifi_only || options_->limited_only;
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003261 if (!is_dumpstate_restricted) {
3262 // Snapshot the system trace now (if running) to avoid that dumpstate's
3263 // own activity pushes out interesting data from the trace ring buffer.
3264 // The trace file is added to the zip by MaybeAddSystemTraceToZip().
3265 MaybeSnapshotSystemTrace();
Yohei Yukawa95305b32021-03-09 07:54:27 -08003266
Kean Mariotti853b73a2023-07-27 12:40:30 +00003267 // Invoke critical dumpsys to preserve system state, before doing anything else.
3268 RunDumpsysCritical();
3269
Kean Mariotti306633e2022-09-05 16:30:47 +00003270 // Snapshot the UI traces now (if running).
3271 // The trace files will be added to bugreport later.
3272 MaybeSnapshotUiTraces();
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003273 }
Kean Mariotti853b73a2023-07-27 12:40:30 +00003274
3275 MaybeTakeEarlyScreenshot();
Gavin Corkery6968f552020-11-22 18:09:05 +00003276 onUiIntensiveBugreportDumpsFinished(calling_uid);
3277 MaybeCheckUserConsent(calling_uid, calling_package);
3278 if (options_->telephony_only) {
3279 DumpstateTelephonyOnly(calling_package);
3280 } else if (options_->wifi_only) {
3281 DumpstateWifiOnly();
3282 } else if (options_->limited_only) {
3283 DumpstateLimitedOnly();
Elis Elliott8e401ad2023-08-08 11:18:59 +00003284 } else if (options_->onboarding_only) {
3285 DumpstateOnboardingOnly();
Gavin Corkery6968f552020-11-22 18:09:05 +00003286 } else {
Nandana Dutt4be45d12018-09-26 15:04:23 +01003287 // Dump state for the default case. This also drops root.
Jichao Lie89d9c12019-11-21 19:02:51 -08003288 RunStatus s = DumpstateDefaultAfterCritical();
Nandana Dutt5c390032019-03-12 10:52:56 +00003289 if (s != RunStatus::OK) {
Nandana Duttaac6f582019-07-26 14:32:47 +01003290 if (s == RunStatus::USER_CONSENT_DENIED) {
Nandana Dutt5c390032019-03-12 10:52:56 +00003291 HandleUserConsentDenied();
3292 }
3293 return s;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08003294 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07003295 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07003296
Felipe Leme55b42a62015-11-10 17:39:08 -08003297 /* close output if needed */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003298 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003299
Abhijeet Kaure370d682019-10-01 16:49:30 +01003300 // Zip the (now complete) .tmp file within the internal directory.
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003301 ATRACE_BEGIN("FinalizeFile");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003302 FinalizeFile();
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003303 ATRACE_END();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003304
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003305 // Share the final file with the caller if the user has consented or Shell is the caller.
Nandana Duttd2f5f082019-01-18 17:13:52 +00003306 Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
Gavin Corkerya44686c2022-11-23 18:16:51 +00003307 if (CalledByApi() && !options_->is_consent_deferred) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003308 status = CopyBugreportIfUserConsented(calling_uid);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003309 if (status != Dumpstate::RunStatus::OK &&
3310 status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3311 // Do an early return if there were errors. We make an exception for consent
3312 // timing out because it's possible the user got distracted. In this case the
3313 // bugreport is not shared but made available for manual retrieval.
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003314 MYLOGI("User denied consent. Returning\n");
Nandana Duttd2f5f082019-01-18 17:13:52 +00003315 return status;
3316 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003317 if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3318 MYLOGI(
3319 "Did not receive user consent yet."
3320 " Will not copy the bugreport artifacts to caller.\n");
Abhijeet Kaur57627412019-04-17 16:00:09 +01003321 const String16 incidentcompanion("incidentcompanion");
3322 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
3323 if (ics != nullptr) {
3324 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3325 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3326 consent_callback_.get());
3327 } else {
3328 MYLOGD("Unable to cancel user consent; incidentcompanion service unavailable\n");
3329 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003330 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003331 }
3332
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003333 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003334 if (options_->do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09003335 for (int i = 0; i < 3; i++) {
3336 Vibrate(75);
3337 usleep((75 + 50) * 1000);
3338 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003339 }
3340
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003341 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
3342 progress_->GetInitialMax());
3343 progress_->Save();
3344 MYLOGI("done (id %d)\n", id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003345
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003346 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08003347
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003348 if (control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07003349 MYLOGD("Closing control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003350 close(control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07003351 }
3352
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003353 tombstone_data_.clear();
3354 anr_data_.clear();
Woody Lin20767a92022-11-29 15:50:24 +08003355 shutdown_checkpoints_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01003356
Nandana Duttd2f5f082019-01-18 17:13:52 +00003357 return (consent_callback_ != nullptr &&
3358 consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
3359 ? USER_CONSENT_TIMED_OUT
3360 : RunStatus::OK;
3361}
3362
Paul Chang0d2aad72020-02-13 20:04:03 +08003363void Dumpstate::MaybeTakeEarlyScreenshot() {
3364 if (!options_->do_screenshot || !do_early_screenshot_) {
3365 return;
3366 }
3367
3368 TakeScreenshot();
3369}
3370
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003371void Dumpstate::MaybeSnapshotSystemTrace() {
Kean Mariotti853b73a2023-07-27 12:40:30 +00003372 // When capturing traces via bugreport handler (BH), this function will be invoked twice:
3373 // 1) When BH invokes IDumpstate::PreDumpUiData()
3374 // 2) When BH invokes IDumpstate::startBugreport(flags = BUGREPORT_USE_PREDUMPED_UI_DATA)
3375 // In this case we don't want to re-invoke perfetto in step 2.
3376 // In all other standard invocation states, this function is invoked once
3377 // without the flag BUGREPORT_USE_PREDUMPED_UI_DATA.
3378 if (options_->use_predumped_ui_data) {
3379 return;
3380 }
3381
3382 // If a stale file exists already, remove it.
3383 unlink(SYSTEM_TRACE_SNAPSHOT);
3384
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003385 // If a background system trace is happening and is marked as "suitable for
3386 // bugreport" (i.e. bugreport_score > 0 in the trace config), this command
3387 // will stop it and serialize into SYSTEM_TRACE_SNAPSHOT. In the (likely)
3388 // case that no trace is ongoing, this command is a no-op.
3389 // Note: this should not be enqueued as we need to freeze the trace before
3390 // dumpstate starts. Otherwise the trace ring buffers will contain mostly
3391 // the dumpstate's own activity which is irrelevant.
Kean Mariotti853b73a2023-07-27 12:40:30 +00003392 RunCommand("SERIALIZE PERFETTO TRACE", {"perfetto", "--save-for-bugreport"},
3393 CommandOptions::WithTimeout(10).DropRoot().CloseAllFileDescriptorsOnExec().Build());
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003394 // MaybeAddSystemTraceToZip() will take care of copying the trace in the zip
3395 // file in the later stages.
3396}
3397
Kean Mariotti306633e2022-09-05 16:30:47 +00003398void Dumpstate::MaybeSnapshotUiTraces() {
3399 if (PropertiesHelper::IsUserBuild() || options_->use_predumped_ui_data) {
3400 return;
3401 }
3402
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003403 const std::vector<std::vector<std::string>> dumpTracesForBugReportCommands = {
3404 {"dumpsys", "activity", "service", "SystemUIService", "WMShell", "protolog",
3405 "save-for-bugreport"},
3406 {"dumpsys", "activity", "service", "SystemUIService", "WMShell", "transitions", "tracing",
3407 "save-for-bugreport"},
3408 {"cmd", "input_method", "tracing", "save-for-bugreport"},
3409 {"cmd", "window", "tracing", "save-for-bugreport"},
3410 {"cmd", "window", "shell", "tracing", "save-for-bugreport"},
3411 };
Hongwei Wang39229132023-01-24 15:09:59 -08003412
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003413 for (const auto& command : dumpTracesForBugReportCommands) {
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003414 RunCommand(
3415 // Empty name because it's not intended to be classified as a bugreport section.
3416 // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003417 "", command,
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003418 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
3419 }
Kean Mariotti306633e2022-09-05 16:30:47 +00003420}
3421
3422void Dumpstate::MaybeAddUiTracesToZip() {
3423 if (PropertiesHelper::IsUserBuild()) {
3424 return;
3425 }
3426
3427 ds.AddDir(WMTRACE_DATA_DIR, false);
Yohei Yukawa95305b32021-03-09 07:54:27 -08003428}
3429
Paul Changeb4b4642020-05-28 22:05:47 +08003430void Dumpstate::onUiIntensiveBugreportDumpsFinished(int32_t calling_uid) {
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003431 if (multiuser_get_app_id(calling_uid) == AID_SHELL || !CalledByApi()) {
Paul Changc490e662020-04-11 18:14:09 +08003432 return;
3433 }
3434 if (listener_ != nullptr) {
3435 // Let listener know ui intensive bugreport dumps are finished, then it can do event
3436 // handling if required.
Paul Changeb4b4642020-05-28 22:05:47 +08003437 listener_->onUiIntensiveBugreportDumpsFinished();
Paul Changc490e662020-04-11 18:14:09 +08003438 }
3439}
3440
Jichao Lie89d9c12019-11-21 19:02:51 -08003441void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) {
Gavin Corkerya44686c2022-11-23 18:16:51 +00003442 if (multiuser_get_app_id(calling_uid) == AID_SHELL ||
3443 !CalledByApi() || options_->is_consent_deferred) {
3444 // No need to get consent for shell triggered dumpstates, or not
3445 // through bugreporting API (i.e. no fd to copy back), or when consent
3446 // is deferred.
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003447 return;
3448 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003449 consent_callback_ = new ConsentCallback();
3450 const String16 incidentcompanion("incidentcompanion");
3451 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
Jichao Lie89d9c12019-11-21 19:02:51 -08003452 android::String16 package(calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003453 if (ics != nullptr) {
3454 MYLOGD("Checking user consent via incidentcompanion service\n");
Steven Leeb573eb82022-11-29 22:31:35 +08003455 int flags = 0x1; // IncidentManager.FLAG_CONFIRMATION_DIALOG
3456 if (IsConsentlessBugreportAllowed(*options_)) {
3457 flags |= 0x2; // IncidentManager.FLAG_ALLOW_CONSENTLESS_BUGREPORT
3458 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003459 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
Steven Leeb573eb82022-11-29 22:31:35 +08003460 calling_uid, package, String16(), String16(), flags, consent_callback_.get());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003461 } else {
3462 MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
3463 }
3464}
3465
Nandana Dutt5c390032019-03-12 10:52:56 +00003466bool Dumpstate::IsUserConsentDenied() const {
3467 return ds.consent_callback_ != nullptr &&
3468 ds.consent_callback_->getResult() == UserConsentResult::DENIED;
3469}
3470
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01003471bool Dumpstate::CalledByApi() const {
3472 return ds.options_->bugreport_fd.get() != -1 ? true : false;
3473}
3474
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003475void Dumpstate::CleanupTmpFiles() {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003476 android::os::UnlinkAndLogOnError(tmp_path_);
3477 android::os::UnlinkAndLogOnError(screenshot_path_);
3478 android::os::UnlinkAndLogOnError(path_);
Gavin Corkery789d7a52021-02-24 23:52:35 +00003479 if (dump_traces_path != nullptr) {
3480 android::os::UnlinkAndLogOnError(dump_traces_path);
3481 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003482}
3483
Rhed Jao5377d792020-07-16 17:37:39 +08003484void Dumpstate::EnableParallelRunIfNeeded() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003485 if (!PropertiesHelper::IsParallelRun()) {
Rhed Jao5377d792020-07-16 17:37:39 +08003486 return;
3487 }
3488 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003489 zip_entry_tasks_ = std::make_unique<TaskQueue>();
Rhed Jao5377d792020-07-16 17:37:39 +08003490}
3491
3492void Dumpstate::ShutdownDumpPool() {
3493 if (dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08003494 dump_pool_.reset();
Rhed Jao5377d792020-07-16 17:37:39 +08003495 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003496 if (zip_entry_tasks_) {
3497 zip_entry_tasks_->run(/* do_cancel = */true);
3498 zip_entry_tasks_ = nullptr;
3499 }
3500}
3501
3502void Dumpstate::EnqueueAddZipEntryAndCleanupIfNeeded(const std::string& entry_name,
3503 const std::string& entry_path) {
3504 auto func_add_zip_entry_and_cleanup = [=](bool task_cancelled) {
3505 if (!task_cancelled) {
3506 AddZipEntry(entry_name, entry_path);
3507 }
3508 android::os::UnlinkAndLogOnError(entry_path);
3509 };
3510 if (zip_entry_tasks_) {
3511 // Enqueues AddZipEntryAndCleanup function if the parallel run is enabled.
3512 zip_entry_tasks_->add(func_add_zip_entry_and_cleanup, _1);
3513 } else {
3514 // Invokes AddZipEntryAndCleanup immediately
3515 std::invoke(func_add_zip_entry_and_cleanup, /* task_cancelled = */false);
3516 }
Rhed Jao5377d792020-07-16 17:37:39 +08003517}
3518
Nandana Duttd2f5f082019-01-18 17:13:52 +00003519Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
3520 MYLOGD("User denied consent; deleting files and returning\n");
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003521 CleanupTmpFiles();
Nandana Duttd2f5f082019-01-18 17:13:52 +00003522 return USER_CONSENT_DENIED;
3523}
3524
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003525Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented(int32_t calling_uid) {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003526 // If the caller has asked to copy the bugreport over to their directory, we need explicit
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003527 // user consent (unless the caller is Shell).
3528 UserConsentResult consent_result;
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003529 if (multiuser_get_app_id(calling_uid) == AID_SHELL) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003530 consent_result = UserConsentResult::APPROVED;
3531 } else {
3532 consent_result = consent_callback_->getResult();
3533 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003534 if (consent_result == UserConsentResult::UNAVAILABLE) {
3535 // User has not responded yet.
3536 uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
Hunter Knepshield70610fa2020-01-03 15:27:33 -08003537 // Telephony is a fast report type, particularly on user builds where information may be
3538 // more aggressively limited. To give the user time to read the consent dialog, increase the
3539 // timeout.
3540 uint64_t timeout_ms = options_->telephony_only ? TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS
3541 : USER_CONSENT_TIMEOUT_MS;
3542 if (elapsed_ms < timeout_ms) {
3543 uint delay_seconds = (timeout_ms - elapsed_ms) / 1000;
Nandana Duttd2f5f082019-01-18 17:13:52 +00003544 MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
3545 sleep(delay_seconds);
3546 }
3547 consent_result = consent_callback_->getResult();
3548 }
3549 if (consent_result == UserConsentResult::DENIED) {
3550 // User has explicitly denied sharing with the app. To be safe delete the
3551 // internal bugreport & tmp files.
3552 return HandleUserConsentDenied();
3553 }
3554 if (consent_result == UserConsentResult::APPROVED) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00003555 bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
3556 if (copy_succeeded) {
3557 android::os::UnlinkAndLogOnError(path_);
Abhijeet Kaur9ce94672020-04-01 17:22:36 +01003558 if (options_->do_screenshot &&
3559 options_->screenshot_fd.get() != -1 &&
3560 !options_->is_screenshot_copied) {
3561 copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
3562 options_->screenshot_fd.get());
3563 options_->is_screenshot_copied = copy_succeeded;
3564 if (copy_succeeded) {
3565 android::os::UnlinkAndLogOnError(screenshot_path_);
3566 }
3567 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003568 }
3569 return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
3570 } else if (consent_result == UserConsentResult::UNAVAILABLE) {
3571 // consent_result is still UNAVAILABLE. The user has likely not responded yet.
3572 // Since we do not have user consent to share the bugreport it does not get
3573 // copied over to the calling app but remains in the internal directory from
3574 // where the user can manually pull it.
Paul Changce644212021-05-11 16:06:45 +08003575 std::string final_path = GetPath(".zip");
3576 bool copy_succeeded = android::os::CopyFileToFile(path_, final_path);
3577 if (copy_succeeded) {
3578 android::os::UnlinkAndLogOnError(path_);
3579 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003580 return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
3581 }
3582 // Unknown result; must be a programming error.
3583 MYLOGE("Unknown user consent result:%d\n", consent_result);
3584 return Dumpstate::RunStatus::ERROR;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003585}
3586
Nandana Duttf02564e2019-02-15 15:24:24 +00003587Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003588 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
3589 Dumpstate::RunStatus status = options->Initialize(argc, argv);
3590 if (status == Dumpstate::RunStatus::OK) {
Nandana Duttf02564e2019-02-15 15:24:24 +00003591 SetOptions(std::move(options));
Nandana Duttd2f5f082019-01-18 17:13:52 +00003592 // When directly running dumpstate binary, the output is not expected to be written
3593 // to any external file descriptor.
Nandana Duttf02564e2019-02-15 15:24:24 +00003594 assert(options_->bugreport_fd.get() == -1);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003595
3596 // calling_uid and calling_package are for user consent to share the bugreport with
Abhijeet Kaura407fb82020-03-27 12:51:12 +00003597 // an app; they are irrelevant here because bugreport is triggered via command line.
3598 // Update Last ID before calling Run().
3599 Initialize();
Nikhil Kumarb70622a2023-06-15 15:37:19 +01003600 status = Run(0 /* calling_uid */, "" /* calling_package */);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003601 }
Nandana Duttf02564e2019-02-15 15:24:24 +00003602 return status;
3603}
3604
3605/* Main entry point for dumpstate binary. */
3606int run_main(int argc, char* argv[]) {
3607 Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003608
3609 switch (status) {
3610 case Dumpstate::RunStatus::OK:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003611 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003612 case Dumpstate::RunStatus::HELP:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003613 ShowUsage();
3614 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003615 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003616 fprintf(stderr, "Invalid combination of args\n");
3617 ShowUsage();
3618 exit(1);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003619 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003620 FALLTHROUGH_INTENDED;
3621 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3622 FALLTHROUGH_INTENDED;
3623 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003624 exit(2);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003625 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003626}
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003627
3628// TODO(111441001): Default DumpOptions to sensible values.
3629Dumpstate::Dumpstate(const std::string& version)
3630 : pid_(getpid()),
3631 options_(new Dumpstate::DumpOptions()),
Nandana Dutt402a8392019-06-14 14:25:13 +01003632 last_reported_percent_progress_(0),
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003633 version_(version),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003634 now_(time(nullptr)),
3635 open_socket_fn_(open_socket) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003636}
3637
3638Dumpstate& Dumpstate::GetInstance() {
3639 static Dumpstate singleton_(android::base::GetProperty("dumpstate.version", VERSION_CURRENT));
3640 return singleton_;
3641}
3642
Rhed Jao5377d792020-07-16 17:37:39 +08003643DurationReporter::DurationReporter(const std::string& title, bool logcat_only, bool verbose,
3644 int duration_fd) : title_(title), logcat_only_(logcat_only), verbose_(verbose),
3645 duration_fd_(duration_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003646 if (!title_.empty()) {
3647 started_ = Nanotime();
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003648 if (title_.find("SHOW MAP") == std::string::npos) {
3649 ATRACE_ASYNC_BEGIN(title_.c_str(), 0);
3650 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003651 }
3652}
3653
3654DurationReporter::~DurationReporter() {
3655 if (!title_.empty()) {
3656 float elapsed = (float)(Nanotime() - started_) / NANOS_PER_SEC;
chenqiwuaf8b2d92019-12-12 18:53:51 +08003657 if (elapsed >= .5f || verbose_) {
3658 MYLOGD("Duration of '%s': %.2fs\n", title_.c_str(), elapsed);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003659 }
chenqiwuaf8b2d92019-12-12 18:53:51 +08003660 if (!logcat_only_) {
3661 // Use "Yoda grammar" to make it easier to grep|sort sections.
Rhed Jao5377d792020-07-16 17:37:39 +08003662 dprintf(duration_fd_, "------ %.3fs was the duration of '%s' ------\n",
3663 elapsed, title_.c_str());
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003664 }
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003665 if (title_.find("SHOW MAP") == std::string::npos) {
3666 ATRACE_ASYNC_END(title_.c_str(), 0);
3667 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003668 }
3669}
3670
3671const int32_t Progress::kDefaultMax = 5000;
3672
3673Progress::Progress(const std::string& path) : Progress(Progress::kDefaultMax, 1.1, path) {
3674}
3675
3676Progress::Progress(int32_t initial_max, int32_t progress, float growth_factor)
3677 : Progress(initial_max, growth_factor, "") {
3678 progress_ = progress;
3679}
3680
3681Progress::Progress(int32_t initial_max, float growth_factor, const std::string& path)
3682 : initial_max_(initial_max),
3683 progress_(0),
3684 max_(initial_max),
3685 growth_factor_(growth_factor),
3686 n_runs_(0),
3687 average_max_(0),
3688 path_(path) {
3689 if (!path_.empty()) {
3690 Load();
3691 }
3692}
3693
3694void Progress::Load() {
3695 MYLOGD("Loading stats from %s\n", path_.c_str());
3696 std::string content;
3697 if (!android::base::ReadFileToString(path_, &content)) {
3698 MYLOGI("Could not read stats from %s; using max of %d\n", path_.c_str(), max_);
3699 return;
3700 }
3701 if (content.empty()) {
3702 MYLOGE("No stats (empty file) on %s; using max of %d\n", path_.c_str(), max_);
3703 return;
3704 }
3705 std::vector<std::string> lines = android::base::Split(content, "\n");
3706
3707 if (lines.size() < 1) {
3708 MYLOGE("Invalid stats on file %s: not enough lines (%d). Using max of %d\n", path_.c_str(),
3709 (int)lines.size(), max_);
3710 return;
3711 }
3712 char* ptr;
3713 n_runs_ = strtol(lines[0].c_str(), &ptr, 10);
3714 average_max_ = strtol(ptr, nullptr, 10);
3715 if (n_runs_ <= 0 || average_max_ <= 0 || n_runs_ > STATS_MAX_N_RUNS ||
3716 average_max_ > STATS_MAX_AVERAGE) {
3717 MYLOGE("Invalid stats line on file %s: %s\n", path_.c_str(), lines[0].c_str());
3718 initial_max_ = Progress::kDefaultMax;
3719 } else {
3720 initial_max_ = average_max_;
3721 }
3722 max_ = initial_max_;
3723
3724 MYLOGI("Average max progress: %d in %d runs; estimated max: %d\n", average_max_, n_runs_, max_);
3725}
3726
3727void Progress::Save() {
3728 int32_t total = n_runs_ * average_max_ + progress_;
3729 int32_t runs = n_runs_ + 1;
3730 int32_t average = floor(((float)total) / runs);
3731 MYLOGI("Saving stats (total=%d, runs=%d, average=%d) on %s\n", total, runs, average,
3732 path_.c_str());
3733 if (path_.empty()) {
3734 return;
3735 }
3736
3737 std::string content = android::base::StringPrintf("%d %d\n", runs, average);
3738 if (!android::base::WriteStringToFile(content, path_)) {
3739 MYLOGE("Could not save stats on %s\n", path_.c_str());
3740 }
3741}
3742
3743int32_t Progress::Get() const {
3744 return progress_;
3745}
3746
3747bool Progress::Inc(int32_t delta_sec) {
3748 bool changed = false;
3749 if (delta_sec >= 0) {
3750 progress_ += delta_sec;
3751 if (progress_ > max_) {
3752 int32_t old_max = max_;
3753 max_ = floor((float)progress_ * growth_factor_);
3754 MYLOGD("Adjusting max progress from %d to %d\n", old_max, max_);
3755 changed = true;
3756 }
3757 }
3758 return changed;
3759}
3760
3761int32_t Progress::GetMax() const {
3762 return max_;
3763}
3764
3765int32_t Progress::GetInitialMax() const {
3766 return initial_max_;
3767}
3768
3769void Progress::Dump(int fd, const std::string& prefix) const {
3770 const char* pr = prefix.c_str();
3771 dprintf(fd, "%sprogress: %d\n", pr, progress_);
3772 dprintf(fd, "%smax: %d\n", pr, max_);
3773 dprintf(fd, "%sinitial_max: %d\n", pr, initial_max_);
3774 dprintf(fd, "%sgrowth_factor: %0.2f\n", pr, growth_factor_);
3775 dprintf(fd, "%spath: %s\n", pr, path_.c_str());
3776 dprintf(fd, "%sn_runs: %d\n", pr, n_runs_);
3777 dprintf(fd, "%saverage_max: %d\n", pr, average_max_);
3778}
3779
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003780std::string Dumpstate::GetPath(const std::string& suffix) const {
3781 return GetPath(bugreport_internal_dir_, suffix);
3782}
3783
3784std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
3785 return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
3786 name_.c_str(), suffix.c_str());
3787}
3788
3789void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
3790 progress_ = std::move(progress);
3791}
3792
3793void for_each_userid(void (*func)(int), const char *header) {
3794 std::string title = header == nullptr ? "for_each_userid" : android::base::StringPrintf(
3795 "for_each_userid(%s)", header);
3796 DurationReporter duration_reporter(title);
3797 if (PropertiesHelper::IsDryRun()) return;
3798
3799 DIR *d;
3800 struct dirent *de;
3801
3802 if (header) printf("\n------ %s ------\n", header);
3803 func(0);
3804
3805 if (!(d = opendir("/data/system/users"))) {
3806 printf("Failed to open /data/system/users (%s)\n", strerror(errno));
3807 return;
3808 }
3809
3810 while ((de = readdir(d))) {
3811 int userid;
3812 if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
3813 continue;
3814 }
3815 func(userid);
3816 }
3817
3818 closedir(d);
3819}
3820
3821static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
3822 DIR *d;
3823 struct dirent *de;
3824
3825 if (!(d = opendir("/proc"))) {
3826 printf("Failed to open /proc (%s)\n", strerror(errno));
3827 return;
3828 }
3829
3830 if (header) printf("\n------ %s ------\n", header);
3831 while ((de = readdir(d))) {
3832 if (ds.IsUserConsentDenied()) {
3833 MYLOGE(
3834 "Returning early because user denied consent to share bugreport with calling app.");
3835 closedir(d);
3836 return;
3837 }
3838 int pid;
3839 int fd;
3840 char cmdpath[255];
3841 char cmdline[255];
3842
3843 if (!(pid = atoi(de->d_name))) {
3844 continue;
3845 }
3846
3847 memset(cmdline, 0, sizeof(cmdline));
3848
3849 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
3850 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3851 TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
3852 close(fd);
3853 if (cmdline[0]) {
3854 helper(pid, cmdline, arg);
3855 continue;
3856 }
3857 }
3858
3859 // if no cmdline, a kernel thread has comm
3860 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
3861 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3862 TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
3863 close(fd);
3864 if (cmdline[1]) {
3865 cmdline[0] = '[';
3866 size_t len = strcspn(cmdline, "\f\b\r\n");
3867 cmdline[len] = ']';
3868 cmdline[len+1] = '\0';
3869 }
3870 }
3871 if (!cmdline[0]) {
3872 strcpy(cmdline, "N/A");
3873 }
3874 helper(pid, cmdline, arg);
3875 }
3876
3877 closedir(d);
3878}
3879
3880static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
3881 for_each_pid_func *func = (for_each_pid_func*) arg;
3882 func(pid, cmdline);
3883}
3884
3885void for_each_pid(for_each_pid_func func, const char *header) {
3886 std::string title = header == nullptr ? "for_each_pid"
3887 : android::base::StringPrintf("for_each_pid(%s)", header);
3888 DurationReporter duration_reporter(title);
3889 if (PropertiesHelper::IsDryRun()) return;
3890
3891 __for_each_pid(for_each_pid_helper, header, (void *) func);
3892}
3893
3894static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
3895 DIR *d;
3896 struct dirent *de;
3897 char taskpath[255];
3898 for_each_tid_func *func = (for_each_tid_func *) arg;
3899
3900 snprintf(taskpath, sizeof(taskpath), "/proc/%d/task", pid);
3901
3902 if (!(d = opendir(taskpath))) {
3903 printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
3904 return;
3905 }
3906
3907 func(pid, pid, cmdline);
3908
3909 while ((de = readdir(d))) {
3910 if (ds.IsUserConsentDenied()) {
3911 MYLOGE(
3912 "Returning early because user denied consent to share bugreport with calling app.");
3913 closedir(d);
3914 return;
3915 }
3916 int tid;
3917 int fd;
3918 char commpath[255];
3919 char comm[255];
3920
3921 if (!(tid = atoi(de->d_name))) {
3922 continue;
3923 }
3924
3925 if (tid == pid)
3926 continue;
3927
3928 snprintf(commpath, sizeof(commpath), "/proc/%d/comm", tid);
3929 memset(comm, 0, sizeof(comm));
3930 if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
3931 strcpy(comm, "N/A");
3932 } else {
3933 char *c;
3934 TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
3935 close(fd);
3936
3937 c = strrchr(comm, '\n');
3938 if (c) {
3939 *c = '\0';
3940 }
3941 }
3942 func(pid, tid, comm);
3943 }
3944
3945 closedir(d);
3946}
3947
3948void for_each_tid(for_each_tid_func func, const char *header) {
3949 std::string title = header == nullptr ? "for_each_tid"
3950 : android::base::StringPrintf("for_each_tid(%s)", header);
3951 DurationReporter duration_reporter(title);
3952
3953 if (PropertiesHelper::IsDryRun()) return;
3954
3955 __for_each_pid(for_each_tid_helper, header, (void *) func);
3956}
3957
3958void show_wchan(int pid, int tid, const char *name) {
3959 if (PropertiesHelper::IsDryRun()) return;
3960
3961 char path[255];
3962 char buffer[255];
3963 int fd, ret, save_errno;
3964 char name_buffer[255];
3965
3966 memset(buffer, 0, sizeof(buffer));
3967
3968 snprintf(path, sizeof(path), "/proc/%d/wchan", tid);
3969 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
3970 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
3971 return;
3972 }
3973
3974 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3975 save_errno = errno;
3976 close(fd);
3977
3978 if (ret < 0) {
3979 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
3980 return;
3981 }
3982
3983 snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
3984 pid == tid ? 0 : 3, "", name);
3985
3986 printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
3987
3988 return;
3989}
3990
3991// print time in centiseconds
3992static void snprcent(char *buffer, size_t len, size_t spc,
3993 unsigned long long time) {
3994 static long hz; // cache discovered hz
3995
3996 if (hz <= 0) {
3997 hz = sysconf(_SC_CLK_TCK);
3998 if (hz <= 0) {
3999 hz = 1000;
4000 }
4001 }
4002
4003 // convert to centiseconds
4004 time = (time * 100 + (hz / 2)) / hz;
4005
4006 char str[16];
4007
4008 snprintf(str, sizeof(str), " %llu.%02u",
4009 time / 100, (unsigned)(time % 100));
4010 size_t offset = strlen(buffer);
4011 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
4012 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
4013}
4014
4015// print permille as a percent
4016static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
4017 char str[16];
4018
4019 snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
4020 size_t offset = strlen(buffer);
4021 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
4022 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
4023}
4024
4025void show_showtime(int pid, const char *name) {
4026 if (PropertiesHelper::IsDryRun()) return;
4027
4028 char path[255];
4029 char buffer[1023];
4030 int fd, ret, save_errno;
4031
4032 memset(buffer, 0, sizeof(buffer));
4033
4034 snprintf(path, sizeof(path), "/proc/%d/stat", pid);
4035 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
4036 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
4037 return;
4038 }
4039
4040 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
4041 save_errno = errno;
4042 close(fd);
4043
4044 if (ret < 0) {
4045 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
4046 return;
4047 }
4048
4049 // field 14 is utime
4050 // field 15 is stime
4051 // field 42 is iotime
4052 unsigned long long utime = 0, stime = 0, iotime = 0;
4053 if (sscanf(buffer,
4054 "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
4055 "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
4056 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
4057 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
4058 &utime, &stime, &iotime) != 3) {
4059 return;
4060 }
4061
4062 unsigned long long total = utime + stime;
4063 if (!total) {
4064 return;
4065 }
4066
4067 unsigned permille = (iotime * 1000 + (total / 2)) / total;
4068 if (permille > 1000) {
4069 permille = 1000;
4070 }
4071
4072 // try to beautify and stabilize columns at <80 characters
4073 snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
4074 if ((name[0] != '[') || utime) {
4075 snprcent(buffer, sizeof(buffer), 57, utime);
4076 }
4077 snprcent(buffer, sizeof(buffer), 65, stime);
4078 if ((name[0] != '[') || iotime) {
4079 snprcent(buffer, sizeof(buffer), 73, iotime);
4080 }
4081 if (iotime) {
4082 snprdec(buffer, sizeof(buffer), 79, permille);
4083 }
4084 puts(buffer); // adds a trailing newline
4085
4086 return;
4087}
4088
4089void do_dmesg() {
4090 const char *title = "KERNEL LOG (dmesg)";
4091 DurationReporter duration_reporter(title);
4092 printf("------ %s ------\n", title);
4093
4094 if (PropertiesHelper::IsDryRun()) return;
4095
4096 /* Get size of kernel buffer */
4097 int size = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
4098 if (size <= 0) {
4099 printf("Unexpected klogctl return value: %d\n\n", size);
4100 return;
4101 }
4102 char *buf = (char *) malloc(size + 1);
4103 if (buf == nullptr) {
4104 printf("memory allocation failed\n\n");
4105 return;
4106 }
4107 int retval = klogctl(KLOG_READ_ALL, buf, size);
4108 if (retval < 0) {
4109 printf("klogctl failure\n\n");
4110 free(buf);
4111 return;
4112 }
4113 buf[retval] = '\0';
4114 printf("%s\n\n", buf);
4115 free(buf);
4116 return;
4117}
4118
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004119int Dumpstate::DumpFile(const std::string& title, const std::string& path) {
4120 DurationReporter duration_reporter(title);
4121
4122 int status = DumpFileToFd(STDOUT_FILENO, title, path);
4123
4124 UpdateProgress(WEIGHT_FILE);
4125
4126 return status;
4127}
4128
4129int read_file_as_long(const char *path, long int *output) {
4130 int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
4131 if (fd < 0) {
4132 int err = errno;
4133 MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
4134 return -1;
4135 }
4136 char buffer[50];
4137 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
4138 if (bytes_read == -1) {
4139 MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
4140 return -2;
4141 }
4142 if (bytes_read == 0) {
4143 MYLOGE("File %s is empty\n", path);
4144 return -3;
4145 }
4146 *output = atoi(buffer);
4147 return 0;
4148}
4149
4150/* calls skip to gate calling dump_from_fd recursively
4151 * in the specified directory. dump_from_fd defaults to
4152 * dump_file_from_fd above when set to NULL. skip defaults
4153 * to false when set to NULL. dump_from_fd will always be
4154 * called with title NULL.
4155 */
4156int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
4157 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4158 DurationReporter duration_reporter(title);
4159 DIR *dirp;
4160 struct dirent *d;
4161 char *newpath = nullptr;
4162 const char *slash = "/";
4163 int retval = 0;
4164
4165 if (!title.empty()) {
4166 printf("------ %s (%s) ------\n", title.c_str(), dir);
4167 }
4168 if (PropertiesHelper::IsDryRun()) return 0;
4169
4170 if (dir[strlen(dir) - 1] == '/') {
4171 ++slash;
4172 }
4173 dirp = opendir(dir);
4174 if (dirp == nullptr) {
4175 retval = -errno;
4176 MYLOGE("%s: %s\n", dir, strerror(errno));
4177 return retval;
4178 }
4179
4180 if (!dump_from_fd) {
4181 dump_from_fd = dump_file_from_fd;
4182 }
4183 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4184 if ((d->d_name[0] == '.')
4185 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4186 || (d->d_name[1] == '\0'))) {
4187 continue;
4188 }
4189 asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
4190 (d->d_type == DT_DIR) ? "/" : "");
4191 if (!newpath) {
4192 retval = -errno;
4193 continue;
4194 }
4195 if (skip && (*skip)(newpath)) {
4196 continue;
4197 }
4198 if (d->d_type == DT_DIR) {
4199 int ret = dump_files("", newpath, skip, dump_from_fd);
4200 if (ret < 0) {
4201 retval = ret;
4202 }
4203 continue;
4204 }
4205 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
4206 if (fd.get() < 0) {
4207 retval = -1;
4208 printf("*** %s: %s\n", newpath, strerror(errno));
4209 continue;
4210 }
4211 (*dump_from_fd)(nullptr, newpath, fd.get());
4212 }
4213 closedir(dirp);
4214 if (!title.empty()) {
4215 printf("\n");
4216 }
4217 return retval;
4218}
4219
4220/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
4221 * it's possible to avoid issues where opening the file itself can get
4222 * stuck.
4223 */
4224int dump_file_from_fd(const char *title, const char *path, int fd) {
4225 if (PropertiesHelper::IsDryRun()) return 0;
4226
4227 int flags = fcntl(fd, F_GETFL);
4228 if (flags == -1) {
4229 printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
4230 return -1;
4231 } else if (!(flags & O_NONBLOCK)) {
4232 printf("*** %s: fd must have O_NONBLOCK set.\n", path);
4233 return -1;
4234 }
4235 return DumpFileFromFdToFd(title, path, fd, STDOUT_FILENO, PropertiesHelper::IsDryRun());
4236}
4237
4238int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004239 const CommandOptions& options, bool verbose_duration, int out_fd) {
4240 DurationReporter duration_reporter(title, false /* logcat_only */,
4241 verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004242
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004243 int status = RunCommandToFd(out_fd, title, full_command, options);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004244
4245 /* TODO: for now we're simplifying the progress calculation by using the
4246 * timeout as the weight. It's a good approximation for most cases, except when calling dumpsys,
4247 * where its weight should be much higher proportionally to its timeout.
4248 * Ideally, it should use a options.EstimatedDuration() instead...*/
4249 UpdateProgress(options.Timeout());
4250
4251 return status;
4252}
4253
4254void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
Rhed Jaoe017f982020-07-21 17:58:41 +08004255 const CommandOptions& options, long dumpsysTimeoutMs, int out_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004256 long timeout_ms = dumpsysTimeoutMs > 0 ? dumpsysTimeoutMs : options.TimeoutInMs();
4257 std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-T", std::to_string(timeout_ms)};
4258 dumpsys.insert(dumpsys.end(), dumpsys_args.begin(), dumpsys_args.end());
Rhed Jaoe017f982020-07-21 17:58:41 +08004259 RunCommand(title, dumpsys, options, false, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004260}
4261
Dieter Hsu105ad0c2020-09-29 15:23:33 +08004262static int open_socket(const char* service) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004263 int s = android_get_control_socket(service);
4264 if (s < 0) {
4265 MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
4266 return -1;
4267 }
4268 fcntl(s, F_SETFD, FD_CLOEXEC);
4269
4270 // Set backlog to 0 to make sure that queue size will be minimum.
4271 // In Linux, because the minimum queue will be 1, connect() will be blocked
4272 // if the other clients already called connect() and the connection request was not accepted.
4273 if (listen(s, 0) < 0) {
4274 MYLOGE("listen(control socket): %s\n", strerror(errno));
4275 return -1;
4276 }
4277
4278 struct sockaddr addr;
4279 socklen_t alen = sizeof(addr);
Abhijeet Kaur2113cae2019-09-13 09:24:15 +01004280 int fd = accept4(s, &addr, &alen, SOCK_CLOEXEC);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004281
4282 // Close socket just after accept(), to make sure that connect() by client will get error
4283 // when the socket is used by the other services.
4284 // There is still a race condition possibility between accept and close, but there is no way
4285 // to close-on-accept atomically.
4286 // See detail; b/123306389#comment25
4287 close(s);
4288
4289 if (fd < 0) {
4290 MYLOGE("accept(control socket): %s\n", strerror(errno));
4291 return -1;
4292 }
4293
4294 return fd;
4295}
4296
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004297// TODO: should call is_valid_output_file and/or be merged into it.
4298void create_parent_dirs(const char *path) {
4299 char *chp = const_cast<char *> (path);
4300
4301 /* skip initial slash */
4302 if (chp[0] == '/')
4303 chp++;
4304
4305 /* create leading directories, if necessary */
4306 struct stat dir_stat;
4307 while (chp && chp[0]) {
4308 chp = strchr(chp, '/');
4309 if (chp) {
4310 *chp = 0;
4311 if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
4312 MYLOGI("Creating directory %s\n", path);
4313 if (mkdir(path, 0770)) { /* drwxrwx--- */
4314 MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
4315 } else if (chown(path, AID_SHELL, AID_SHELL)) {
4316 MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
4317 }
4318 }
4319 *chp++ = '/';
4320 }
4321 }
4322}
4323
4324bool _redirect_to_file(FILE* redirect, char* path, int truncate_flag) {
4325 create_parent_dirs(path);
4326
4327 int fd = TEMP_FAILURE_RETRY(open(path,
4328 O_WRONLY | O_CREAT | truncate_flag | O_CLOEXEC | O_NOFOLLOW,
4329 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
4330 if (fd < 0) {
4331 MYLOGE("%s: %s\n", path, strerror(errno));
4332 return false;
4333 }
4334
4335 TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
4336 close(fd);
4337 return true;
4338}
4339
4340bool redirect_to_file(FILE* redirect, char* path) {
4341 return _redirect_to_file(redirect, path, O_TRUNC);
4342}
4343
4344bool redirect_to_existing_file(FILE* redirect, char* path) {
4345 return _redirect_to_file(redirect, path, O_APPEND);
4346}
4347
4348void dump_route_tables() {
4349 DurationReporter duration_reporter("DUMP ROUTE TABLES");
4350 if (PropertiesHelper::IsDryRun()) return;
4351 const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
4352 ds.DumpFile("RT_TABLES", RT_TABLES_PATH);
4353 FILE* fp = fopen(RT_TABLES_PATH, "re");
4354 if (!fp) {
4355 printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
4356 return;
4357 }
4358 char table[16];
4359 // Each line has an integer (the table number), a space, and a string (the table name). We only
4360 // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
4361 // Add a fixed max limit so this doesn't go awry.
4362 for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
4363 RunCommand("ROUTE TABLE IPv4", {"ip", "-4", "route", "show", "table", table});
4364 RunCommand("ROUTE TABLE IPv6", {"ip", "-6", "route", "show", "table", table});
4365 }
4366 fclose(fp);
4367}
4368
Li Li830179f2022-01-04 12:53:29 -08004369void dump_frozen_cgroupfs(const char *dir, int level,
4370 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4371 DIR *dirp;
4372 struct dirent *d;
4373 char *newpath = nullptr;
4374
4375 dirp = opendir(dir);
4376 if (dirp == nullptr) {
4377 MYLOGE("%s: %s\n", dir, strerror(errno));
4378 return;
4379 }
4380
4381 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4382 if ((d->d_name[0] == '.')
4383 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4384 || (d->d_name[1] == '\0'))) {
4385 continue;
4386 }
4387 if (d->d_type == DT_DIR) {
4388 asprintf(&newpath, "%s/%s/", dir, d->d_name);
4389 if (!newpath) {
4390 continue;
4391 }
4392 if (level == 0 && !strncmp(d->d_name, "uid_", 4)) {
4393 dump_frozen_cgroupfs(newpath, 1, dump_from_fd);
4394 } else if (level == 1 && !strncmp(d->d_name, "pid_", 4)) {
4395 char *freezer = nullptr;
4396 asprintf(&freezer, "%s/%s", newpath, "cgroup.freeze");
4397 if (freezer) {
4398 FILE* fp = fopen(freezer, "r");
4399 if (fp != NULL) {
4400 int frozen;
4401 fscanf(fp, "%d", &frozen);
4402 if (frozen > 0) {
4403 dump_files("", newpath, skip_none, dump_from_fd);
4404 }
4405 fclose(fp);
4406 }
4407 free(freezer);
4408 }
4409 }
4410 }
4411 }
4412 closedir(dirp);
4413}
4414
4415void dump_frozen_cgroupfs() {
Li Li830179f2022-01-04 12:53:29 -08004416 MYLOGD("Adding frozen processes from %s\n", CGROUPFS_DIR);
4417 DurationReporter duration_reporter("FROZEN CGROUPFS");
4418 if (PropertiesHelper::IsDryRun()) return;
4419 dump_frozen_cgroupfs(CGROUPFS_DIR, 0, _add_file_from_fd);
4420}
4421
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004422void Dumpstate::UpdateProgress(int32_t delta_sec) {
4423 if (progress_ == nullptr) {
4424 MYLOGE("UpdateProgress: progress_ not set\n");
4425 return;
4426 }
Rhed Jaobf63d8a2020-07-21 15:42:55 +08004427 // This function updates progress related members of the dumpstate and reports
4428 // progress percentage to the bugreport client. Since it could be called by
4429 // different dump tasks at the same time if the parallel run is enabled, a
4430 // mutex lock is necessary here to synchronize the call.
4431 std::lock_guard<std::recursive_mutex> lock(mutex_);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004432
4433 // Always update progess so stats can be tuned...
Nandana Dutt402a8392019-06-14 14:25:13 +01004434 progress_->Inc(delta_sec);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004435
4436 // ...but only notifiy listeners when necessary.
4437 if (!options_->do_progress_updates) return;
4438
4439 int progress = progress_->Get();
4440 int max = progress_->GetMax();
Nandana Dutt402a8392019-06-14 14:25:13 +01004441 int percent = 100 * progress / max;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004442
Nandana Dutt402a8392019-06-14 14:25:13 +01004443 if (last_reported_percent_progress_ > 0 && percent <= last_reported_percent_progress_) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004444 return;
4445 }
Nandana Dutt402a8392019-06-14 14:25:13 +01004446 last_reported_percent_progress_ = percent;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004447
4448 if (control_socket_fd_ >= 0) {
4449 dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
4450 fsync(control_socket_fd_);
4451 }
4452
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004453 if (listener_ != nullptr) {
Nandana Dutt235c6672019-11-14 15:22:32 +00004454 if (percent % 10 == 0) {
4455 // We don't want to spam logcat, so only log multiples of 10.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004456 MYLOGD("Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004457 } else {
4458 // stderr is ignored on normal invocations, but useful when calling
4459 // /system/bin/dumpstate directly for debuggging.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004460 fprintf(stderr, "Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004461 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004462
4463 listener_->onProgress(percent);
4464 }
4465}
4466
4467void Dumpstate::TakeScreenshot(const std::string& path) {
4468 const std::string& real_path = path.empty() ? screenshot_path_ : path;
4469 int status =
4470 RunCommand("", {"/system/bin/screencap", "-p", real_path},
4471 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
4472 if (status == 0) {
4473 MYLOGD("Screenshot saved on %s\n", real_path.c_str());
4474 } else {
4475 MYLOGE("Failed to take screenshot on %s\n", real_path.c_str());
4476 }
Paul Chang0d2aad72020-02-13 20:04:03 +08004477 if (listener_ != nullptr) {
4478 // Show a visual indication to indicate screenshot is taken via
4479 // IDumpstateListener.onScreenshotTaken()
4480 listener_->onScreenshotTaken(status == 0);
4481 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004482}
4483
4484bool is_dir(const char* pathname) {
4485 struct stat info;
4486 if (stat(pathname, &info) == -1) {
4487 return false;
4488 }
4489 return S_ISDIR(info.st_mode);
4490}
4491
4492time_t get_mtime(int fd, time_t default_mtime) {
4493 struct stat info;
4494 if (fstat(fd, &info) == -1) {
4495 return default_mtime;
4496 }
4497 return info.st_mtime;
4498}