blob: 408b926ea70cdd4ad405897b7f549ef0d7eaa542 [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 Huanga99452a2022-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
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001037 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001038 RunCommand("LAST LOGCAT", {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable",
1039 "-v", "uid", "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001040}
1041
Mike Ma5c267872019-08-21 11:31:34 -07001042static void DumpIncidentReport() {
Mike Ma5c267872019-08-21 11:31:34 -07001043 const std::string path = ds.bugreport_internal_dir_ + "/tmp_incident_report";
1044 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1045 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1046 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1047 if (fd < 0) {
1048 MYLOGE("Could not open %s to dump incident report.\n", path.c_str());
1049 return;
1050 }
Kevin Jeonfa64e642023-07-27 11:36:41 -04001051 RunCommandToFd(fd, "", {"incident", "-u"},
1052 CommandOptions::WithTimeout(PropertiesHelper::IsStrictRun() ? 20 : 120).Build());
Mike Ma5c267872019-08-21 11:31:34 -07001053 bool empty = 0 == lseek(fd, 0, SEEK_END);
1054 if (!empty) {
1055 // Use a different name from "incident.proto"
1056 // /proto/incident.proto is reserved for incident service dump
1057 // i.e. metadata for debugging.
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001058 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "incident_report" + kProtoExt,
1059 path);
1060 } else {
1061 unlink(path.c_str());
Mike Ma5c267872019-08-21 11:31:34 -07001062 }
Mike Ma5c267872019-08-21 11:31:34 -07001063}
1064
Aaron Huanga99452a2022-04-27 18:51:16 +08001065static void DumpNetstatsProto() {
1066 const std::string path = ds.bugreport_internal_dir_ + "/tmp_netstats_proto";
1067 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1068 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1069 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1070 if (fd < 0) {
1071 MYLOGE("Could not open %s to dump netstats proto.\n", path.c_str());
1072 return;
1073 }
1074 RunCommandToFd(fd, "", {"dumpsys", "netstats", "--proto"},
Kevin Jeon2fb3dd62022-09-28 18:48:55 +00001075 CommandOptions::WithTimeout(5).Build());
Aaron Huanga99452a2022-04-27 18:51:16 +08001076 bool empty = 0 == lseek(fd, 0, SEEK_END);
1077 if (!empty) {
1078 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "netstats" + kProtoExt,
1079 path);
1080 } else {
1081 unlink(path.c_str());
1082 }
1083}
1084
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001085static void MaybeAddSystemTraceToZip() {
1086 // This function copies into the .zip the system trace that was snapshotted
1087 // by the early call to MaybeSnapshotSystemTrace(), if any background
1088 // tracing was happening.
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001089 if (!ds.has_system_trace_) {
1090 // No background trace was happening at the time dumpstate was invoked.
1091 return;
1092 }
1093 ds.AddZipEntry(
1094 ZIP_ROOT_DIR + SYSTEM_TRACE_SNAPSHOT,
1095 SYSTEM_TRACE_SNAPSHOT);
1096 android::os::UnlinkAndLogOnError(SYSTEM_TRACE_SNAPSHOT);
1097}
1098
Sunny Goyal35949782019-11-19 15:54:36 -08001099static void DumpVisibleWindowViews() {
Sunny Goyal35949782019-11-19 15:54:36 -08001100 DurationReporter duration_reporter("VISIBLE WINDOW VIEWS");
1101 const std::string path = ds.bugreport_internal_dir_ + "/tmp_visible_window_views";
1102 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1103 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1104 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1105 if (fd < 0) {
1106 MYLOGE("Could not open %s to dump visible views.\n", path.c_str());
1107 return;
1108 }
1109 RunCommandToFd(fd, "", {"cmd", "window", "dump-visible-window-views"},
Kevin Jeon774abde2022-09-28 18:20:43 +00001110 CommandOptions::WithTimeout(10).Build());
Sunny Goyal35949782019-11-19 15:54:36 -08001111 bool empty = 0 == lseek(fd, 0, SEEK_END);
1112 if (!empty) {
1113 ds.AddZipEntry("visible_windows.zip", path);
1114 } else {
1115 MYLOGW("Failed to dump visible windows\n");
1116 }
1117 unlink(path.c_str());
1118}
1119
Jayachandran Ca94c7172017-06-10 15:08:12 -07001120static void DumpIpTablesAsRoot() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001121 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
1122 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +09001123 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001124 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +09001125 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
1126 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
1127 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
1128 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001129}
1130
Woody Lin20767a92022-11-29 15:50:24 +08001131static void DumpShutdownCheckpoints() {
1132 const bool shutdown_checkpoints_dumped = AddDumps(
1133 ds.shutdown_checkpoints_.begin(), ds.shutdown_checkpoints_.end(),
1134 "SHUTDOWN CHECKPOINTS", false /* add_to_zip */);
1135 if (!shutdown_checkpoints_dumped) {
1136 printf("*** NO SHUTDOWN CHECKPOINTS to dump in %s\n\n",
1137 SHUTDOWN_CHECKPOINTS_DIR.c_str());
1138 }
1139}
1140
David Andersond9ba4752018-12-11 18:26:59 -08001141static void DumpDynamicPartitionInfo() {
1142 if (!::android::base::GetBoolProperty("ro.boot.dynamic_partitions", false)) {
1143 return;
1144 }
1145
1146 RunCommand("LPDUMP", {"lpdump", "--all"});
David Anderson6650ade2019-10-02 15:18:59 -07001147 RunCommand("DEVICE-MAPPER", {"gsid", "dump-device-mapper"});
David Andersond9ba4752018-12-11 18:26:59 -08001148}
1149
Chris Morin5a50d482022-02-01 17:41:18 -08001150static void AddAnrTraceDir(const std::string& anr_traces_dir) {
Narayan Kamath8f788292017-05-25 13:20:39 +01001151 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
1152 anr_traces_dir.c_str());
1153
1154 // If we're here, dump_traces_path will always be a temporary file
1155 // (created with mkostemp or similar) that contains dumps taken earlier
1156 // on in the process.
1157 if (dump_traces_path != nullptr) {
Chris Morin5a50d482022-02-01 17:41:18 -08001158 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
1159 dump_traces_path);
1160 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
Narayan Kamath8f788292017-05-25 13:20:39 +01001161
1162 const int ret = unlink(dump_traces_path);
1163 if (ret == -1) {
1164 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
1165 strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -07001166 }
1167 }
1168
Narayan Kamathbd863722017-06-01 18:50:12 +01001169 // Add a specific message for the first ANR Dump.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001170 if (ds.anr_data_.size() > 0) {
Chris Morin5a50d482022-02-01 17:41:18 -08001171 // The "last" ANR will always be present in the body of the main entry.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001172 AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1,
Chris Morin5a50d482022-02-01 17:41:18 -08001173 "VM TRACES AT LAST ANR", false /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001174
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001175 // Historical ANRs are always included as separate entries in the bugreport zip file.
Chris Morin5a50d482022-02-01 17:41:18 -08001176 AddDumps(ds.anr_data_.begin(), ds.anr_data_.end(),
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001177 "HISTORICAL ANR", true /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001178 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +01001179 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
1180 }
1181}
1182
1183static void AddAnrTraceFiles() {
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001184 std::string anr_traces_dir = "/data/anr";
Narayan Kamath8f788292017-05-25 13:20:39 +01001185
Chris Morin5a50d482022-02-01 17:41:18 -08001186 AddAnrTraceDir(anr_traces_dir);
Narayan Kamath8f788292017-05-25 13:20:39 +01001187
Makoto Onuki83ec63f2019-01-31 17:08:59 -08001188 RunCommand("ANR FILES", {"ls", "-lt", ANR_DIR});
1189
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001190 // Slow traces for slow operations.
Felipe Lemee184f662016-10-27 10:04:47 -07001191 struct stat st;
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001192 int i = 0;
1193 while (true) {
1194 const std::string slow_trace_path =
1195 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
1196 if (stat(slow_trace_path.c_str(), &st)) {
1197 // No traces file at this index, done with the files.
1198 break;
Felipe Lemee184f662016-10-27 10:04:47 -07001199 }
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001200 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
1201 i++;
Felipe Lemee184f662016-10-27 10:04:47 -07001202 }
1203}
1204
Wei Wang509bb5d2017-06-09 14:42:12 -07001205static void DumpBlockStatFiles() {
1206 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -07001207
Wei Wang1dc1ef52017-06-12 11:28:37 -07001208 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
1209
1210 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001211 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1212 return;
1213 }
1214
1215 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -07001216 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001217 if ((d->d_name[0] == '.')
1218 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1219 || (d->d_name[1] == '\0'))) {
1220 continue;
1221 }
1222 const std::string new_path =
1223 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1224 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1225 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1226 printf("\n");
1227 }
Wei Wang1dc1ef52017-06-12 11:28:37 -07001228 return;
Wei Wang509bb5d2017-06-09 14:42:12 -07001229}
Jayachandran Ca94c7172017-06-10 15:08:12 -07001230
1231static void DumpPacketStats() {
1232 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
Jayachandran Ca94c7172017-06-10 15:08:12 -07001233}
1234
1235static void DumpIpAddrAndRules() {
1236 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
Ray Chencbf278a2023-11-20 07:49:45 +00001237 RunCommand("NETWORK INTERFACES", {"ip", "-s", "link"});
Jayachandran Ca94c7172017-06-10 15:08:12 -07001238 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1239 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1240 RunCommand("IP RULES", {"ip", "rule", "show"});
1241 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1242}
1243
Nandana Dutt5c390032019-03-12 10:52:56 +00001244static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, int priority,
1245 std::chrono::milliseconds timeout,
1246 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001247 auto start = std::chrono::steady_clock::now();
Vishnu Naire97d6122018-01-18 13:58:56 -08001248 sp<android::IServiceManager> sm = defaultServiceManager();
1249 Dumpsys dumpsys(sm.get());
Vishnu Naire97d6122018-01-18 13:58:56 -08001250 Vector<String16> args;
1251 Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
Vishnu Naire97d6122018-01-18 13:58:56 -08001252 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1253 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001254 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001255 std::string path(title);
1256 path.append(" - ").append(String8(service).c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -08001257 size_t bytes_written = 0;
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001258 if (PropertiesHelper::IsDryRun()) {
1259 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1260 dumpsys.writeDumpFooter(STDOUT_FILENO, service, std::chrono::milliseconds(1));
1261 } else {
Devin Mooref492c1a2023-03-15 19:19:03 +00001262 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP | Dumpsys::TYPE_PID |
1263 Dumpsys::TYPE_CLIENTS | Dumpsys::TYPE_THREAD,
Devin Mooreae68df22023-02-24 20:59:51 +00001264 service, args);
1265 if (status == OK) {
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001266 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1267 std::chrono::duration<double> elapsed_seconds;
1268 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH &&
1269 service == String16("meminfo")) {
1270 // Use a longer timeout for meminfo, since 30s is not always enough.
1271 status = dumpsys.writeDump(STDOUT_FILENO, service, 60s,
1272 /* as_proto = */ false, elapsed_seconds,
1273 bytes_written);
1274 } else {
1275 status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
1276 /* as_proto = */ false, elapsed_seconds,
1277 bytes_written);
1278 }
1279 dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
1280 bool dump_complete = (status == OK);
1281 dumpsys.stopDumpThread(dump_complete);
Devin Moorecdfa4602023-03-16 20:49:39 +00001282 } else {
1283 MYLOGE("Failed to start dump thread for service: %s, status: %d",
1284 String8(service).c_str(), status);
Gavin Corkeryfac7e2b2021-07-08 22:39:02 +01001285 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001286 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001287
1288 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1289 std::chrono::steady_clock::now() - start);
1290 if (elapsed_duration > timeout) {
1291 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1292 elapsed_duration.count());
1293 break;
1294 }
1295 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001296 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001297}
1298
Vishnu Nair64afc022018-02-01 15:29:34 -08001299static void RunDumpsysText(const std::string& title, int priority,
1300 std::chrono::milliseconds timeout,
1301 std::chrono::milliseconds service_timeout) {
1302 DurationReporter duration_reporter(title);
1303 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1304 fsync(STDOUT_FILENO);
1305 RunDumpsysTextByPriority(title, priority, timeout, service_timeout);
1306}
1307
1308/* Dump all services registered with Normal or Default priority. */
Nandana Dutt5c390032019-03-12 10:52:56 +00001309static Dumpstate::RunStatus RunDumpsysTextNormalPriority(const std::string& title,
1310 std::chrono::milliseconds timeout,
1311 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001312 DurationReporter duration_reporter(title);
1313 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1314 fsync(STDOUT_FILENO);
1315 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout,
1316 service_timeout);
Nandana Dutt5c390032019-03-12 10:52:56 +00001317
1318 RETURN_IF_USER_DENIED_CONSENT();
1319
1320 return RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1321 service_timeout);
Vishnu Nair64afc022018-02-01 15:29:34 -08001322}
1323
Nandana Dutt5c390032019-03-12 10:52:56 +00001324static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priority,
1325 std::chrono::milliseconds timeout,
1326 std::chrono::milliseconds service_timeout) {
Vishnu Naire97d6122018-01-18 13:58:56 -08001327 sp<android::IServiceManager> sm = defaultServiceManager();
1328 Dumpsys dumpsys(sm.get());
1329 Vector<String16> args;
1330 Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
1331 DurationReporter duration_reporter(title);
1332
1333 auto start = std::chrono::steady_clock::now();
1334 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
1335 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001336 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001337 std::string path(kProtoPath);
1338 path.append(String8(service).c_str());
1339 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
1340 path.append("_CRITICAL");
1341 } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
1342 path.append("_HIGH");
1343 }
1344 path.append(kProtoExt);
Steven Morelandcbd69fc2021-07-20 20:45:43 +00001345 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP, service, args);
Vishnu Naire97d6122018-01-18 13:58:56 -08001346 if (status == OK) {
1347 status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
1348 bool dumpTerminated = (status == OK);
1349 dumpsys.stopDumpThread(dumpTerminated);
1350 }
1351 ZipWriter::FileEntry file_entry;
1352 ds.zip_writer_->GetLastEntry(&file_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -08001353
1354 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1355 std::chrono::steady_clock::now() - start);
1356 if (elapsed_duration > timeout) {
1357 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1358 elapsed_duration.count());
1359 break;
1360 }
1361 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001362 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001363}
1364
Nandana Dutta7db6342018-11-21 14:53:34 +00001365// Runs dumpsys on services that must dump first and will take less than 100ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001366static Dumpstate::RunStatus RunDumpsysCritical() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001367 RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1368 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Nandana Dutt5c390032019-03-12 10:52:56 +00001369
1370 RETURN_IF_USER_DENIED_CONSENT();
1371
1372 return RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1373 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Vishnu Nair780b1282017-10-10 13:57:24 -07001374}
1375
1376// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001377static Dumpstate::RunStatus RunDumpsysHigh() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001378 // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
1379 // high priority. Reduce timeout once they are able to dump in a shorter time or
1380 // moved to a parallel task.
1381 RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1382 /* timeout= */ 90s, /* service_timeout= */ 30s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001383
1384 RETURN_IF_USER_DENIED_CONSENT();
1385
1386 return RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1387 /* timeout= */ 5s, /* service_timeout= */ 1s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001388}
1389
1390// Runs dumpsys on services that must dump but can take up to 10s to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001391static Dumpstate::RunStatus RunDumpsysNormal() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001392 RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001393
1394 RETURN_IF_USER_DENIED_CONSENT();
1395
1396 return RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1397 /* timeout= */ 90s, /* service_timeout= */ 10s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001398}
1399
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001400/*
1401 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1402 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1403 * if it's not running in the parallel task.
1404 */
1405static void DumpHals(int out_fd = STDOUT_FILENO) {
Yifan Hong30528a22020-08-07 18:24:06 -07001406 RunCommand("HARDWARE HALS", {"lshal", "--all", "--types=all"},
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001407 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build(),
1408 false, out_fd);
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001409
Steven Moreland44cd9482018-01-04 16:24:13 -08001410 using android::hidl::manager::V1_0::IServiceManager;
1411 using android::hardware::defaultServiceManager;
1412
1413 sp<IServiceManager> sm = defaultServiceManager();
1414 if (sm == nullptr) {
1415 MYLOGE("Could not retrieve hwservicemanager to dump hals.\n");
1416 return;
1417 }
1418
1419 auto ret = sm->list([&](const auto& interfaces) {
1420 for (const std::string& interface : interfaces) {
1421 std::string cleanName = interface;
Steven Morelandc6b1fc22023-07-26 23:53:58 +00001422 std::replace_if(
1423 cleanName.begin(), cleanName.end(),
1424 [](char c) {
1425 return !isalnum(c) && std::string("@-_.").find(c) == std::string::npos;
1426 },
1427 '_');
Nandana Dutt979388e2018-11-30 16:48:55 +00001428 const std::string path = ds.bugreport_internal_dir_ + "/lshal_debug_" + cleanName;
Steven Moreland44cd9482018-01-04 16:24:13 -08001429
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001430 bool empty = false;
Steven Moreland44cd9482018-01-04 16:24:13 -08001431 {
1432 auto fd = android::base::unique_fd(
1433 TEMP_FAILURE_RETRY(open(path.c_str(),
1434 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1435 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1436 if (fd < 0) {
1437 MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str());
1438 continue;
1439 }
1440 RunCommandToFd(fd,
1441 "",
Steven Morelandc81cd3c2018-01-18 14:36:26 -08001442 {"lshal", "debug", "-E", interface},
Steven Moreland44cd9482018-01-04 16:24:13 -08001443 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1444
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001445 empty = 0 == lseek(fd, 0, SEEK_END);
Steven Moreland44cd9482018-01-04 16:24:13 -08001446 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001447 if (!empty) {
1448 ds.EnqueueAddZipEntryAndCleanupIfNeeded("lshal-debug/" + cleanName + ".txt",
1449 path);
1450 } else {
1451 unlink(path.c_str());
1452 }
Steven Moreland44cd9482018-01-04 16:24:13 -08001453 }
1454 });
1455
1456 if (!ret.isOk()) {
1457 MYLOGE("Could not list hals from hwservicemanager.\n");
1458 }
1459}
1460
Devin Moore8df81bb2022-06-08 22:47:02 +00001461// Dump all of the files that make up the vendor interface.
1462// See the files listed in dumpFileList() for the latest list of files.
1463static void DumpVintf() {
Devin Moore16271d92022-09-22 18:28:48 +00001464
1465 const std::string sku = android::base::GetProperty("ro.boot.product.hardware.sku", "");
1466 const auto vintfFiles = android::vintf::details::dumpFileList(sku);
Devin Moore8df81bb2022-06-08 22:47:02 +00001467 for (const auto vintfFile : vintfFiles) {
1468 struct stat st;
1469 if (stat(vintfFile.c_str(), &st) == 0) {
1470 if (S_ISDIR(st.st_mode)) {
1471 ds.AddDir(vintfFile, true /* recursive */);
1472 } else {
1473 ds.EnqueueAddZipEntryAndCleanupIfNeeded(ZIP_ROOT_DIR + vintfFile,
1474 vintfFile);
1475 }
1476 }
1477 }
1478}
1479
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001480static void DumpExternalFragmentationInfo() {
1481 struct stat st;
1482 if (stat("/proc/buddyinfo", &st) != 0) {
1483 MYLOGE("Unable to dump external fragmentation info\n");
1484 return;
1485 }
1486
1487 printf("------ EXTERNAL FRAGMENTATION INFO ------\n");
1488 std::ifstream ifs("/proc/buddyinfo");
1489 auto unusable_index_regex = std::regex{"Node\\s+([0-9]+),\\s+zone\\s+(\\S+)\\s+(.*)"};
1490 for (std::string line; std::getline(ifs, line);) {
1491 std::smatch match_results;
1492 if (std::regex_match(line, match_results, unusable_index_regex)) {
1493 std::stringstream free_pages(std::string{match_results[3]});
1494 std::vector<int> free_pages_per_order(std::istream_iterator<int>{free_pages},
1495 std::istream_iterator<int>());
1496
1497 int total_free_pages = 0;
1498 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1499 total_free_pages += (free_pages_per_order[i] * std::pow(2, i));
1500 }
1501
1502 printf("Node %s, zone %8s", match_results[1].str().c_str(),
1503 match_results[2].str().c_str());
1504
1505 int usable_free_pages = total_free_pages;
1506 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1507 auto unusable_index = (total_free_pages - usable_free_pages) /
1508 static_cast<double>(total_free_pages);
1509 printf(" %5.3f", unusable_index);
1510 usable_free_pages -= (free_pages_per_order[i] * std::pow(2, i));
1511 }
1512
1513 printf("\n");
1514 }
1515 }
1516 printf("\n");
1517}
1518
mhasankd451a472020-05-26 18:02:39 -07001519static void DumpstateLimitedOnly() {
EdenSue8fe4522023-11-20 15:37:23 +08001520 // Trimmed-down version of dumpstate to only include a allowlisted
mhasankd451a472020-05-26 18:02:39 -07001521 // set of logs (system log, event log, and system server / system app
1522 // crashes, and networking logs). See b/136273873 and b/138459828
1523 // for context.
1524 DurationReporter duration_reporter("DUMPSTATE");
1525 unsigned long timeout_ms;
1526 // calculate timeout
1527 timeout_ms = logcat_timeout({"main", "system", "crash"});
1528 RunCommand("SYSTEM LOG",
1529 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1530 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1531 timeout_ms = logcat_timeout({"events"});
1532 RunCommand(
1533 "EVENT LOG",
1534 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1535 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1536
1537 printf("========================================================\n");
1538 printf("== Networking Service\n");
1539 printf("========================================================\n");
1540
1541 RunDumpsys("DUMPSYS NETWORK_SERVICE_LIMITED", {"wifi", "-a"},
1542 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hugo Benichiaa162682020-10-30 23:28:56 +09001543 RunDumpsys("DUMPSYS CONNECTIVITY REQUESTS", {"connectivity", "requests"},
1544 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
mhasankd451a472020-05-26 18:02:39 -07001545
1546 printf("========================================================\n");
1547 printf("== Dropbox crashes\n");
1548 printf("========================================================\n");
1549
1550 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1551 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1552
1553 printf("========================================================\n");
1554 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1555 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1556 printf("========================================================\n");
1557 printf("== dumpstate: done (id %d)\n", ds.id_);
1558 printf("========================================================\n");
1559}
1560
Rhed Jaoe017f982020-07-21 17:58:41 +08001561/*
1562 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1563 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1564 * if it's not running in the parallel task.
1565 */
1566static void DumpCheckins(int out_fd = STDOUT_FILENO) {
1567 dprintf(out_fd, "========================================================\n");
1568 dprintf(out_fd, "== Checkins\n");
1569 dprintf(out_fd, "========================================================\n");
1570
1571 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"}, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001572 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"}, out_fd);
1573 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"}, out_fd);
1574 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"}, out_fd);
1575 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"}, out_fd);
1576}
1577
1578/*
1579 * Runs dumpsys on activity service to dump all application activities, services
1580 * and providers in the device.
1581 *
1582 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1583 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1584 * if it's not running in the parallel task.
1585 */
1586static void DumpAppInfos(int out_fd = STDOUT_FILENO) {
1587 dprintf(out_fd, "========================================================\n");
1588 dprintf(out_fd, "== Running Application Activities\n");
1589 dprintf(out_fd, "========================================================\n");
1590
1591 // The following dumpsys internally collects output from running apps, so it can take a long
1592 // time. So let's extend the timeout.
1593
1594 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1595
1596 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1597
1598 dprintf(out_fd, "========================================================\n");
1599 dprintf(out_fd, "== Running Application Services (platform)\n");
1600 dprintf(out_fd, "========================================================\n");
1601
1602 RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
1603 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1604
1605 dprintf(out_fd, "========================================================\n");
1606 dprintf(out_fd, "== Running Application Services (non-platform)\n");
1607 dprintf(out_fd, "========================================================\n");
1608
1609 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1610 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1611
1612 dprintf(out_fd, "========================================================\n");
1613 dprintf(out_fd, "== Running Application Providers (platform)\n");
1614 dprintf(out_fd, "========================================================\n");
1615
1616 RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
Rhed Jaob049f182021-01-11 21:08:43 +08001617 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001618
1619 dprintf(out_fd, "========================================================\n");
1620 dprintf(out_fd, "== Running Application Providers (non-platform)\n");
1621 dprintf(out_fd, "========================================================\n");
1622
1623 RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1624 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1625}
1626
Nandana Dutt5c390032019-03-12 10:52:56 +00001627// Dumps various things. Returns early with status USER_CONSENT_DENIED if user denies consent
1628// via the consent they are shown. Ignores other errors that occur while running various
1629// commands. The consent checking is currently done around long running tasks, which happen to
1630// be distributed fairly evenly throughout the function.
Kean Mariotti306633e2022-09-05 16:30:47 +00001631Dumpstate::RunStatus Dumpstate::dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001632 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001633
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001634 // Enqueue slow functions into the thread pool, if the parallel run is enabled.
Aaron Huanga99452a2022-04-27 18:51:16 +08001635 std::future<std::string> dump_hals, dump_incident_report, dump_board, dump_checkins,
Kean Mariotti306633e2022-09-05 16:30:47 +00001636 dump_netstats_report, post_process_ui_traces;
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001637 if (ds.dump_pool_) {
1638 // Pool was shutdown in DumpstateDefaultAfterCritical method in order to
Kean Mariotti306633e2022-09-05 16:30:47 +00001639 // drop root user. Restarts it.
1640 ds.dump_pool_->start(/* thread_counts = */3);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001641
Chris Morinbc223142022-02-04 14:17:11 -08001642 dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
1643 dump_incident_report = ds.dump_pool_->enqueueTask(
1644 DUMP_INCIDENT_REPORT_TASK, &DumpIncidentReport);
Aaron Huanga99452a2022-04-27 18:51:16 +08001645 dump_netstats_report = ds.dump_pool_->enqueueTask(
1646 DUMP_NETSTATS_PROTO_TASK, &DumpNetstatsProto);
Chris Morinbc223142022-02-04 14:17:11 -08001647 dump_board = ds.dump_pool_->enqueueTaskWithFd(
1648 DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
1649 dump_checkins = ds.dump_pool_->enqueueTaskWithFd(DUMP_CHECKINS_TASK, &DumpCheckins, _1);
Kean Mariotti306633e2022-09-05 16:30:47 +00001650 post_process_ui_traces = ds.dump_pool_->enqueueTask(
1651 POST_PROCESS_UI_TRACES_TASK, &Dumpstate::MaybePostProcessUiTraces, &ds);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001652 }
1653
Nandana Dutt5c390032019-03-12 10:52:56 +00001654 // Dump various things. Note that anything that takes "long" (i.e. several seconds) should
1655 // check intermittently (if it's intrerruptable like a foreach on pids) and/or should be wrapped
1656 // in a consent check (via RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK).
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001657 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001658 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001659 DumpBlockStatFiles();
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001660 DumpFile("MEMORY INFO", "/proc/meminfo");
1661 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001662 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001663
Kevin Jeon947922b2022-09-21 00:29:18 +00001664 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "BUGREPORT_PROCDUMP", {"bugreport_procdump"},
1665 CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001666
Sunny Goyal35949782019-11-19 15:54:36 -08001667 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpVisibleWindowViews);
1668
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001669 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1670 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1671 DumpFile("SLAB INFO", "/proc/slabinfo");
1672 DumpFile("ZONEINFO", "/proc/zoneinfo");
1673 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1674 DumpFile("BUDDYINFO", "/proc/buddyinfo");
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001675 DumpExternalFragmentationInfo();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001676
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001677 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001678
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001679 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001680 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001681
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001682 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001683 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_hals));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001684 } else {
1685 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_HALS_TASK, DumpHals);
1686 }
Steven Moreland81b429e2017-01-31 19:50:46 -08001687
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001688 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001689 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001690 struct stat s;
1691 if (stat("/proc/modules", &s) != 0) {
1692 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1693 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001694 RunCommand("LSMOD", {"lsmod"});
Woody Linc198f252021-05-04 16:37:11 +08001695 RunCommand("MODULES INFO",
1696 {"sh", "-c", "cat /proc/modules | cut -d' ' -f1 | "
1697 " while read MOD ; do echo modinfo:$MOD ; modinfo $MOD ; "
1698 "done"}, CommandOptions::AS_ROOT);
Felipe Lemee4eca582016-06-10 17:48:08 -07001699 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001700
Tom Cherryb87dbfa2020-07-28 11:28:53 -07001701 if (android::base::GetBoolProperty("ro.logd.kernel", false)) {
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001702 DoKernelLogcat();
1703 } else {
1704 do_dmesg();
1705 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001706
Devin Moore8df81bb2022-06-08 22:47:02 +00001707 DumpVintf();
1708
Felipe Lemef0292972016-11-22 13:57:05 -08001709 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001710
Jeff Brown1dc94e32014-09-11 14:15:27 -07001711 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001712 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001713
Jack Yu5a6b2e22020-08-14 18:13:35 +08001714 /* Dump Nfc NCI logs */
1715 ds.AddDir("/data/misc/nfc/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001716
Paul Chang0d2aad72020-02-13 20:04:03 +08001717 if (ds.options_->do_screenshot && !ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001718 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001719 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001720 }
1721
Felipe Lemee184f662016-10-27 10:04:47 -07001722 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001723
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001724 MaybeAddSystemTraceToZip();
1725
Narayan Kamath8f788292017-05-25 13:20:39 +01001726 // NOTE: tombstones are always added as separate entries in the zip archive
1727 // and are not interspersed with the main report.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001728 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
Narayan Kamathbd863722017-06-01 18:50:12 +01001729 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001730 if (!tombstones_dumped) {
1731 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001732 }
1733
Jayachandran Ca94c7172017-06-10 15:08:12 -07001734 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001735
Lorenzo Colitti807f2dd2022-05-27 12:48:37 +09001736 RunDumpsys("EBPF MAP STATS", {"connectivity", "trafficcontroller"});
Chenbo Feng276a3b62018-08-07 11:44:49 -07001737
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001738 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001739
Woody Lin20767a92022-11-29 15:50:24 +08001740 DumpShutdownCheckpoints();
1741
Jayachandran Ca94c7172017-06-10 15:08:12 -07001742 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001743
1744 dump_route_tables();
1745
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001746 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1747 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1748 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001749
Nandana Dutt5c390032019-03-12 10:52:56 +00001750 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysHigh);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001751
Chiachang Wang668ede42021-05-17 17:14:20 +08001752 // The dump mechanism in connectivity is refactored due to modularization work. Connectivity can
1753 // only register with a default priority(NORMAL priority). Dumpstate has to call connectivity
1754 // dump with priority parameters to dump high priority information.
1755 RunDumpsys("SERVICE HIGH connectivity", {"connectivity", "--dump-priority", "HIGH"},
1756 CommandOptions::WithTimeout(10).Build());
1757
Elliott Hughes23ccc622017-02-28 10:14:22 -08001758 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001759
Joe Onoratod38bc3a2023-06-29 15:48:28 -07001760 DumpFile("SYSTEM BUILD-TIME RELEASE FLAGS", "/system/etc/build_flags.json");
1761 DumpFile("SYSTEM_EXT BUILD-TIME RELEASE FLAGS", "/system_ext/etc/build_flags.json");
1762 DumpFile("PRODUCT BUILD-TIME RELEASE FLAGS", "/product/etc/build_flags.json");
1763 DumpFile("VENDOR BUILD-TIME RELEASE FLAGS", "/vendor/etc/build_flags.json");
1764
Mårten Kongstad5ad813f2023-09-28 10:09:18 +02001765 RunCommand("ACONFIG FLAGS", {PRINT_FLAGS},
1766 CommandOptions::WithTimeout(10).Always().DropRoot().Build());
Joe Onoratod38bc3a2023-06-29 15:48:28 -07001767
Jin Qianf334d662017-10-10 14:41:37 -07001768 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001769
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001770 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001771
Colin Crossf45fa6b2012-03-26 12:38:26 -07001772 /* Binder state is expensive to look at as it uses a lot of memory. */
Hridya Valsaraju920ba712020-02-09 16:27:01 -08001773 std::string binder_logs_dir = access("/dev/binderfs/binder_logs", R_OK) ?
1774 "/sys/kernel/debug/binder" : "/dev/binderfs/binder_logs";
1775
1776 DumpFile("BINDER FAILED TRANSACTION LOG", binder_logs_dir + "/failed_transaction_log");
1777 DumpFile("BINDER TRANSACTION LOG", binder_logs_dir + "/transaction_log");
1778 DumpFile("BINDER TRANSACTIONS", binder_logs_dir + "/transactions");
1779 DumpFile("BINDER STATS", binder_logs_dir + "/stats");
1780 DumpFile("BINDER STATE", binder_logs_dir + "/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001781
Yifan Hongd90cc652020-02-08 16:52:02 -08001782 ds.AddDir(SNAPSHOTCTL_LOG_DIR, false);
1783
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001784 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001785 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_board));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001786 } else {
1787 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
1788 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001789
Steven Moreland7440ddb2016-12-15 16:13:39 -08001790 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001791 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1792 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001793 // su does not exist on user builds, so try running without it.
1794 // This way any implementations of vril-dump that do not require
1795 // root can run on user builds.
1796 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001797 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001798 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001799 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001800 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001801 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001802 }
1803
Felipe Lemed8b94e52016-12-08 10:21:44 -08001804 printf("========================================================\n");
1805 printf("== Android Framework Services\n");
1806 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001807
Nandana Dutt5c390032019-03-12 10:52:56 +00001808 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001809
Jack He91ff2fe2021-02-18 18:23:43 -08001810 /* Dump Bluetooth HCI logs after getting bluetooth_manager dumpsys */
1811 ds.AddDir("/data/misc/bluetooth/logs", true);
1812
Rhed Jaoe017f982020-07-21 17:58:41 +08001813 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001814 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_checkins));
Rhed Jaoe017f982020-07-21 17:58:41 +08001815 } else {
1816 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_CHECKINS_TASK, DumpCheckins);
1817 }
Dianne Hackborn02bea972013-06-26 18:59:09 -07001818
Rhed Jaoc5f7ec32020-12-22 22:11:08 +08001819 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpAppInfos);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001820
Adrian Roos8b397ab2017-04-04 16:35:44 -07001821 printf("========================================================\n");
1822 printf("== Dropbox crashes\n");
1823 printf("========================================================\n");
1824
1825 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1826 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1827
Felipe Lemed8b94e52016-12-08 10:21:44 -08001828 printf("========================================================\n");
1829 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1830 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1831 printf("========================================================\n");
1832 printf("== dumpstate: done (id %d)\n", ds.id_);
1833 printf("========================================================\n");
Bookatz38472142018-09-28 10:20:24 -07001834
1835 printf("========================================================\n");
1836 printf("== Obtaining statsd metadata\n");
1837 printf("========================================================\n");
1838 // This differs from the usual dumpsys stats, which is the stats report data.
1839 RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
Mike Ma5c267872019-08-21 11:31:34 -07001840
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +09001841 // Add linker configuration directory
1842 ds.AddDir(LINKERCONFIG_DIR, true);
1843
Li Li830179f2022-01-04 12:53:29 -08001844 /* Dump frozen cgroupfs */
1845 dump_frozen_cgroupfs();
Li Li2eedd412021-06-30 15:11:53 -07001846
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001847 if (ds.dump_pool_) {
Aaron Huanga99452a2022-04-27 18:51:16 +08001848 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_netstats_report));
1849 } else {
1850 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_NETSTATS_PROTO_TASK,
1851 DumpNetstatsProto);
1852 }
1853
1854 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001855 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_incident_report));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001856 } else {
1857 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_INCIDENT_REPORT_TASK,
1858 DumpIncidentReport);
1859 }
Mike Ma5c267872019-08-21 11:31:34 -07001860
Kean Mariotti306633e2022-09-05 16:30:47 +00001861 if (ds.dump_pool_) {
1862 WaitForTask(std::move(post_process_ui_traces));
1863 } else {
1864 RUN_SLOW_FUNCTION_AND_LOG(POST_PROCESS_UI_TRACES_TASK, MaybePostProcessUiTraces);
1865 }
1866
1867 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 Menke9bf3b2b2023-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
Nandana Duttcf419a72019-03-14 10:40:17 +00002172Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
Gavin Corkery789d7a52021-02-24 23:52:35 +00002173 const std::string temp_file_pattern = ds.bugreport_internal_dir_ + "/dumptrace_XXXXXX";
Nandana Duttfaafd522019-03-11 09:23:09 +00002174 const size_t buf_size = temp_file_pattern.length() + 1;
2175 std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
2176 memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
2177
2178 // Create a new, empty file to receive all trace dumps.
2179 //
2180 // TODO: This can be simplified once we remove support for the old style
2181 // dumps. We can have a file descriptor passed in to dump_traces instead
2182 // of creating a file, closing it and then reopening it again.
2183 android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
2184 if (fd < 0) {
2185 MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002186 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002187 }
2188
2189 // Nobody should have access to this temporary file except dumpstate, but we
2190 // temporarily grant 'read' to 'others' here because this file is created
2191 // when tombstoned is still running as root, but dumped after dropping. This
2192 // can go away once support for old style dumping has.
2193 const int chmod_ret = fchmod(fd, 0666);
2194 if (chmod_ret < 0) {
2195 MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002196 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002197 }
2198
2199 std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
2200 if (proc.get() == nullptr) {
2201 MYLOGE("opendir /proc failed: %s\n", strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002202 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002203 }
2204
2205 // Number of times process dumping has timed out. If we encounter too many
2206 // failures, we'll give up.
2207 int timeout_failures = 0;
2208 bool dalvik_found = false;
2209
Jayant Chowdharya0a8eb22022-05-20 03:30:09 +00002210 const std::set<int> hal_pids = get_interesting_pids();
Nandana Duttfaafd522019-03-11 09:23:09 +00002211
2212 struct dirent* d;
2213 while ((d = readdir(proc.get()))) {
Nandana Duttcf419a72019-03-14 10:40:17 +00002214 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttfaafd522019-03-11 09:23:09 +00002215 int pid = atoi(d->d_name);
2216 if (pid <= 0) {
2217 continue;
2218 }
2219
Kevin Jeond0f8a982023-04-07 14:27:11 -04002220 // Skip cached processes.
2221 if (IsCached(pid)) {
2222 // For consistency, the header and footer to this message match those
2223 // dumped by debuggerd in the success case.
2224 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
2225 dprintf(fd, "Dump skipped for cached process.\n");
2226 dprintf(fd, "---- end %d ----", pid);
2227 continue;
2228 }
2229
Nandana Duttfaafd522019-03-11 09:23:09 +00002230 const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
2231 std::string exe;
2232 if (!android::base::Readlink(link_name, &exe)) {
2233 continue;
2234 }
2235
2236 bool is_java_process;
2237 if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
2238 // Don't bother dumping backtraces for the zygote.
2239 if (IsZygote(pid)) {
2240 continue;
2241 }
2242
2243 dalvik_found = true;
2244 is_java_process = true;
2245 } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
2246 is_java_process = false;
2247 } else {
2248 // Probably a native process we don't care about, continue.
2249 continue;
2250 }
2251
2252 // If 3 backtrace dumps fail in a row, consider debuggerd dead.
2253 if (timeout_failures == 3) {
2254 dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
2255 break;
2256 }
2257
2258 const uint64_t start = Nanotime();
2259 const int ret = dump_backtrace_to_file_timeout(
Kevin Jeonb8a39362023-04-04 15:00:34 -04002260 pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace, 3, fd);
Nandana Duttfaafd522019-03-11 09:23:09 +00002261
2262 if (ret == -1) {
2263 // For consistency, the header and footer to this message match those
2264 // dumped by debuggerd in the success case.
2265 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
2266 dprintf(fd, "Dump failed, likely due to a timeout.\n");
2267 dprintf(fd, "---- end %d ----", pid);
2268 timeout_failures++;
2269 continue;
2270 }
2271
2272 // We've successfully dumped stack traces, reset the failure count
2273 // and write a summary of the elapsed time to the file and continue with the
2274 // next process.
2275 timeout_failures = 0;
2276
2277 dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
2278 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
2279 }
2280
2281 if (!dalvik_found) {
2282 MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
2283 }
2284
Nandana Duttcf419a72019-03-14 10:40:17 +00002285 *path = file_name_buf.release();
2286 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002287}
2288
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002289static dumpstate_hal_hidl::DumpstateMode GetDumpstateHalModeHidl(
2290 const Dumpstate::BugreportMode bugreport_mode) {
2291 switch (bugreport_mode) {
2292 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2293 return dumpstate_hal_hidl::DumpstateMode::FULL;
2294 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2295 return dumpstate_hal_hidl::DumpstateMode::INTERACTIVE;
2296 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2297 return dumpstate_hal_hidl::DumpstateMode::REMOTE;
2298 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2299 return dumpstate_hal_hidl::DumpstateMode::WEAR;
2300 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2301 return dumpstate_hal_hidl::DumpstateMode::CONNECTIVITY;
2302 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2303 return dumpstate_hal_hidl::DumpstateMode::WIFI;
2304 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2305 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2306 }
2307 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2308}
2309
2310static dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode GetDumpstateHalModeAidl(
2311 const Dumpstate::BugreportMode bugreport_mode) {
2312 switch (bugreport_mode) {
2313 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2314 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::FULL;
2315 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2316 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::INTERACTIVE;
2317 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2318 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::REMOTE;
2319 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2320 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WEAR;
2321 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2322 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::CONNECTIVITY;
2323 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2324 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WIFI;
2325 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2326 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2327 }
2328 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2329}
2330
2331static void DoDumpstateBoardHidl(
2332 const sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_1_0,
2333 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2334 const Dumpstate::BugreportMode bugreport_mode,
2335 const size_t timeout_sec) {
2336
2337 using ScopedNativeHandle =
2338 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
2339 ScopedNativeHandle handle(native_handle_create(static_cast<int>(dumpstate_fds.size()), 0),
2340 [](native_handle_t* handle) {
2341 // we don't close file handle's here
2342 // via native_handle_close(handle)
2343 // instead we let dumpstate_fds close the file handles when
2344 // dumpstate_fds gets destroyed
2345 native_handle_delete(handle);
2346 });
2347 if (handle == nullptr) {
2348 MYLOGE("Could not create native_handle for dumpstate HAL\n");
2349 return;
2350 }
2351
2352 for (size_t i = 0; i < dumpstate_fds.size(); i++) {
2353 handle.get()->data[i] = dumpstate_fds[i].get();
2354 }
2355
2356 // Prefer version 1.1 if available. New devices launching with R are no longer allowed to
2357 // implement just 1.0.
2358 const char* descriptor_to_kill;
2359 using DumpstateBoardTask = std::packaged_task<bool()>;
2360 DumpstateBoardTask dumpstate_board_task;
2361 sp<dumpstate_hal_hidl::IDumpstateDevice> dumpstate_hal(
2362 dumpstate_hal_hidl::IDumpstateDevice::castFrom(dumpstate_hal_1_0));
2363 if (dumpstate_hal != nullptr) {
2364 MYLOGI("Using IDumpstateDevice v1.1 HIDL HAL");
2365
2366 dumpstate_hal_hidl::DumpstateMode dumpstate_hal_mode =
2367 GetDumpstateHalModeHidl(bugreport_mode);
2368
2369 descriptor_to_kill = dumpstate_hal_hidl::IDumpstateDevice::descriptor;
2370 dumpstate_board_task =
2371 DumpstateBoardTask([timeout_sec, dumpstate_hal_mode, dumpstate_hal, &handle]() -> bool {
2372 ::android::hardware::Return<dumpstate_hal_hidl::DumpstateStatus> status =
2373 dumpstate_hal->dumpstateBoard_1_1(handle.get(), dumpstate_hal_mode,
2374 SEC_TO_MSEC(timeout_sec));
2375 if (!status.isOk()) {
2376 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2377 return false;
2378 } else if (status != dumpstate_hal_hidl::DumpstateStatus::OK) {
2379 MYLOGE("dumpstateBoard failed with DumpstateStatus::%s\n",
2380 dumpstate_hal_hidl::toString(status).c_str());
2381 return false;
2382 }
2383 return true;
2384 });
2385 } else {
2386 MYLOGI("Using IDumpstateDevice v1.0 HIDL HAL");
2387
2388 descriptor_to_kill = dumpstate_hal_hidl_1_0::IDumpstateDevice::descriptor;
2389 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal_1_0, &handle]() -> bool {
2390 ::android::hardware::Return<void> status =
2391 dumpstate_hal_1_0->dumpstateBoard(handle.get());
2392 if (!status.isOk()) {
2393 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2394 return false;
2395 }
2396 return true;
2397 });
2398 }
2399 auto result = dumpstate_board_task.get_future();
2400 std::thread(std::move(dumpstate_board_task)).detach();
2401
2402 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2403 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2404 if (!android::base::SetProperty(
2405 "ctl.interface_restart",
2406 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2407 MYLOGE("Couldn't restart dumpstate HAL\n");
2408 }
2409 }
2410 // Wait some time for init to kill dumpstate vendor HAL
2411 constexpr size_t killing_timeout_sec = 10;
2412 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2413 MYLOGE(
2414 "killing dumpstateBoard timed out after %zus, continue and "
2415 "there might be racing in content\n",
2416 killing_timeout_sec);
2417 }
2418}
2419
2420static void DoDumpstateBoardAidl(
2421 const std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal,
2422 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2423 const Dumpstate::BugreportMode bugreport_mode, const size_t timeout_sec) {
2424 MYLOGI("Using IDumpstateDevice AIDL HAL");
2425
2426 const char* descriptor_to_kill;
2427 using DumpstateBoardTask = std::packaged_task<bool()>;
2428 DumpstateBoardTask dumpstate_board_task;
2429 dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode dumpstate_hal_mode =
2430 GetDumpstateHalModeAidl(bugreport_mode);
2431
2432 descriptor_to_kill = dumpstate_hal_aidl::IDumpstateDevice::descriptor;
2433 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal, &dumpstate_fds, dumpstate_hal_mode,
2434 timeout_sec]() -> bool {
2435 auto status = dumpstate_hal->dumpstateBoard(dumpstate_fds, dumpstate_hal_mode, timeout_sec);
2436
2437 if (!status.isOk()) {
2438 MYLOGE("dumpstateBoard failed: %s\n", status.getDescription().c_str());
2439 return false;
2440 }
2441 return true;
2442 });
2443 auto result = dumpstate_board_task.get_future();
2444 std::thread(std::move(dumpstate_board_task)).detach();
2445
2446 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2447 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2448 if (!android::base::SetProperty(
2449 "ctl.interface_restart",
2450 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2451 MYLOGE("Couldn't restart dumpstate HAL\n");
2452 }
2453 }
2454 // Wait some time for init to kill dumpstate vendor HAL
2455 constexpr size_t killing_timeout_sec = 10;
2456 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2457 MYLOGE(
2458 "killing dumpstateBoard timed out after %zus, continue and "
2459 "there might be racing in content\n",
2460 killing_timeout_sec);
2461 }
2462}
2463
2464static std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> GetDumpstateBoardAidlService() {
2465 const std::string aidl_instance_name =
2466 std::string(dumpstate_hal_aidl::IDumpstateDevice::descriptor) + "/default";
2467
2468 if (!AServiceManager_isDeclared(aidl_instance_name.c_str())) {
2469 return nullptr;
2470 }
2471
2472 ndk::SpAIBinder dumpstateBinder(AServiceManager_waitForService(aidl_instance_name.c_str()));
2473
2474 return dumpstate_hal_aidl::IDumpstateDevice::fromBinder(dumpstateBinder);
2475}
2476
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002477void Dumpstate::DumpstateBoard(int out_fd) {
2478 dprintf(out_fd, "========================================================\n");
2479 dprintf(out_fd, "== Board\n");
2480 dprintf(out_fd, "========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08002481
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002482 /*
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002483 * mount debugfs for non-user builds with ro.product.debugfs_restrictions.enabled
Hridya Valsaraju51101602021-04-02 14:32:46 -07002484 * set to true and unmount it after invoking dumpstateBoard_* methods.
2485 * This is to enable debug builds to not have debugfs mounted during runtime.
2486 * It will also ensure that debugfs is only accessed by the dumpstate HAL.
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002487 */
Hridya Valsaraju51101602021-04-02 14:32:46 -07002488 auto mount_debugfs =
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002489 android::base::GetBoolProperty("ro.product.debugfs_restrictions.enabled", false);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002490 if (mount_debugfs) {
2491 RunCommand("mount debugfs", {"mount", "-t", "debugfs", "debugfs", "/sys/kernel/debug"},
2492 AS_ROOT_20);
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002493 RunCommand("chmod debugfs", {"chmod", "0755", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002494 }
2495
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002496 std::vector<std::string> paths;
2497 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07002498 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002499 paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
2500 kDumpstateBoardFiles[i].c_str()));
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002501 remover.emplace_back(android::base::make_scope_guard(
2502 std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002503 }
Jie Song9fbfad02017-06-20 16:29:42 -07002504
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002505 // get dumpstate HAL AIDL implementation
2506 std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal_handle_aidl(
2507 GetDumpstateBoardAidlService());
2508 if (dumpstate_hal_handle_aidl == nullptr) {
2509 MYLOGI("No IDumpstateDevice AIDL implementation\n");
2510 }
2511
2512 // get dumpstate HAL HIDL implementation, only if AIDL HAL implementation not found
2513 sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_handle_hidl_1_0 = nullptr;
2514 if (dumpstate_hal_handle_aidl == nullptr) {
2515 dumpstate_hal_handle_hidl_1_0 = dumpstate_hal_hidl_1_0::IDumpstateDevice::getService();
2516 if (dumpstate_hal_handle_hidl_1_0 == nullptr) {
2517 MYLOGI("No IDumpstateDevice HIDL implementation\n");
2518 }
2519 }
2520
2521 // if neither HIDL nor AIDL implementation found, then return
2522 if (dumpstate_hal_handle_hidl_1_0 == nullptr && dumpstate_hal_handle_aidl == nullptr) {
2523 MYLOGE("Could not find IDumpstateDevice implementation\n");
Wei Wang587eac92018-04-05 12:17:20 -07002524 return;
2525 }
2526
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002527 // this is used to hold the file descriptors and when this variable goes out of scope
2528 // the file descriptors are closed
2529 std::vector<::ndk::ScopedFileDescriptor> dumpstate_fds;
Wei Wang587eac92018-04-05 12:17:20 -07002530
Nandana Dutt5c390032019-03-12 10:52:56 +00002531 // TODO(128270426): Check for consent in between?
Wei Wang587eac92018-04-05 12:17:20 -07002532 for (size_t i = 0; i < paths.size(); i++) {
2533 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
2534
2535 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
2536 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
2537 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
2538 if (fd < 0) {
2539 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
2540 return;
2541 }
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002542
2543 dumpstate_fds.emplace_back(fd.release());
2544 // we call fd.release() here to make sure "fd" does not get closed
2545 // after "fd" goes out of scope after this block.
2546 // "fd" will be closed when "dumpstate_fds" goes out of scope
2547 // i.e. when we exit this function
Wei Wang587eac92018-04-05 12:17:20 -07002548 }
2549
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002550 // Given that bugreport is required to diagnose failures, it's better to set an arbitrary amount
2551 // of timeout for IDumpstateDevice than to block the rest of bugreport. In the timeout case, we
2552 // will kill the HAL and grab whatever it dumped in time.
Michael Eastwood8523ea02022-03-10 16:33:08 -08002553 constexpr size_t timeout_sec = 45;
Wei Wang587eac92018-04-05 12:17:20 -07002554
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002555 if (dumpstate_hal_handle_aidl != nullptr) {
2556 DoDumpstateBoardAidl(dumpstate_hal_handle_aidl, dumpstate_fds, options_->bugreport_mode,
2557 timeout_sec);
2558 } else if (dumpstate_hal_handle_hidl_1_0 != nullptr) {
2559 // run HIDL HAL only if AIDL HAL not found
2560 DoDumpstateBoardHidl(dumpstate_hal_handle_hidl_1_0, dumpstate_fds, options_->bugreport_mode,
2561 timeout_sec);
Wei Wang587eac92018-04-05 12:17:20 -07002562 }
2563
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002564 if (mount_debugfs) {
Hridya Valsaraju51101602021-04-02 14:32:46 -07002565 auto keep_debugfs_mounted =
2566 android::base::GetProperty("persist.dbg.keep_debugfs_mounted", "");
2567 if (keep_debugfs_mounted.empty())
2568 RunCommand("unmount debugfs", {"umount", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002569 }
2570
Wei Wang587eac92018-04-05 12:17:20 -07002571 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
2572 for (size_t i = 0; i < paths.size(); i++) {
2573 struct stat s;
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002574 if (fstat(dumpstate_fds[i].get(), &s) == -1) {
2575 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(), strerror(errno));
Wei Wang587eac92018-04-05 12:17:20 -07002576 file_sizes[i] = -1;
2577 continue;
2578 }
2579 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002580 }
2581
2582 for (size_t i = 0; i < paths.size(); i++) {
2583 if (file_sizes[i] == -1) {
2584 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002585 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002586 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07002587 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002588 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002589 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002590 remover[i].Disable();
2591 EnqueueAddZipEntryAndCleanupIfNeeded(kDumpstateBoardFiles[i], paths[i]);
2592 dprintf(out_fd, "*** See %s entry ***\n", kDumpstateBoardFiles[i].c_str());
Jie Song9fbfad02017-06-20 16:29:42 -07002593 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08002594}
2595
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002596static void ShowUsage() {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002597 fprintf(stderr,
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002598 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o directory] [-p] "
2599 "[-s] [-S] [-q] [-P] [-R] [-L] [-V version]\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002600 " -h: display this help message\n"
2601 " -b: play sound file instead of vibrate, at beginning of job\n"
2602 " -e: play sound file instead of vibrate, at end of job\n"
mhasank2d75c442020-06-11 15:05:25 -07002603 " -o: write to custom directory (only in limited mode)\n"
Abhijeet Kaurbb55a3b2019-06-13 18:07:25 +01002604 " -p: capture screenshot to filename.png\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002605 " -s: write zipped file to control socket (for init)\n"
2606 " -S: write file location to control socket (for init)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002607 " -q: disable vibrate\n"
Abhijeet Kaure370d682019-10-01 16:49:30 +01002608 " -P: send broadcast when started and do progress updates\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002609 " -R: take bugreport in remote mode (shouldn't be used with -P)\n"
Nandana Dutt235864b2019-01-22 12:10:16 +00002610 " -w: start binder service and make it wait for a call to startBugreport\n"
mhasankd451a472020-05-26 18:02:39 -07002611 " -L: output limited information that is safe for submission in feedback reports\n"
Felipe Lemed071c682016-10-20 16:48:00 -07002612 " -v: prints the dumpstate header and exit\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002613}
2614
Wei Liuf87959e2016-08-26 14:51:42 -07002615static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07002616 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07002617}
2618
Felipe Leme1d486fe2016-10-14 18:06:47 -07002619bool Dumpstate::FinishZipFile() {
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002620 // Runs all enqueued adding zip entry and cleanup tasks before finishing the zip file.
2621 if (zip_entry_tasks_) {
2622 zip_entry_tasks_->run(/* do_cancel = */false);
2623 }
2624
Felipe Leme9a523ae2016-10-20 15:10:33 -07002625 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07002626 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07002627 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002628 // Final timestamp
2629 char date[80];
2630 time_t the_real_now_please_stand_up = time(nullptr);
2631 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002632 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002633 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002634
Felipe Leme9a523ae2016-10-20 15:10:33 -07002635 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002636 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08002637 return false;
2638 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07002639 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002640 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08002641 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08002642 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08002643
Felipe Leme0f3fb202016-06-10 17:10:53 -07002644 // Add log file (which contains stderr output) to zip...
2645 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002646 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07002647 MYLOGE("Failed to add dumpstate log to .zip file\n");
2648 return false;
2649 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002650 // TODO: Should truncate the existing file.
2651 // ... and re-open it for further logging.
Nandana Dutta344cb62019-02-22 15:12:35 +00002652 if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
2653 return false;
2654 }
Felipe Leme0f3fb202016-06-10 17:10:53 -07002655 fprintf(stderr, "\n");
2656
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002657 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07002658 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002659 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002660 return false;
2661 }
2662
Felipe Leme1d486fe2016-10-14 18:06:47 -07002663 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
2664 ds.zip_file.reset(nullptr);
2665
Felipe Lemee9d2c542016-11-15 11:48:26 -08002666 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002667 android::os::UnlinkAndLogOnError(tmp_path_);
Felipe Lemec4eee562016-04-21 15:42:55 -07002668
Felipe Leme1e9edc62015-12-21 16:02:13 -08002669 return true;
2670}
Felipe Leme6e01fa62015-11-11 19:35:14 -08002671
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00002672static void SendBroadcast(const std::string& action,
2673 const std::vector<std::string>& args,
2674 int32_t user_id) {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002675 // clang-format off
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00002676 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user",
2677 std::to_string(user_id), "--receiver-foreground",
2678 "--receiver-include-background", "-a", action};
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002679 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08002680
2681 am.insert(am.end(), args.begin(), args.end());
2682
Felipe Leme8d2410e2017-02-08 09:46:08 -08002683 RunCommand("", am,
2684 CommandOptions::WithTimeout(20)
2685 .Log("Sending broadcast: '%s'\n")
2686 .Always()
2687 .DropRoot()
2688 .RedirectStderr()
2689 .Build());
2690}
2691
Felipe Leme35b8cf12017-02-10 15:47:29 -08002692static void Vibrate(int duration_ms) {
2693 // clang-format off
Lais Andrade51156962021-02-22 19:21:35 +00002694 std::vector<std::string> args = {"cmd", "vibrator_manager", "synced", "-f", "-d", "dumpstate",
2695 "oneshot", std::to_string(duration_ms)};
2696 RunCommand("", args,
Felipe Leme35b8cf12017-02-10 15:47:29 -08002697 CommandOptions::WithTimeout(10)
2698 .Log("Vibrate: '%s'\n")
2699 .Always()
2700 .Build());
2701 // clang-format on
2702}
2703
Nandana Dutt979388e2018-11-30 16:48:55 +00002704static void MaybeResolveSymlink(std::string* path) {
2705 std::string resolved_path;
2706 if (android::base::Readlink(*path, &resolved_path)) {
2707 *path = resolved_path;
2708 }
2709}
2710
Nandana Dutt4be45d12018-09-26 15:04:23 +01002711/*
2712 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002713 * and adds the version file. Return false if zip_file could not be open to write.
Nandana Dutt4be45d12018-09-26 15:04:23 +01002714 */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002715static bool PrepareToWriteToFile() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002716 MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2717
Nandana Dutt4be45d12018-09-26 15:04:23 +01002718 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2719 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002720 ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002721 char date[80];
2722 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2723 ds.name_ = date;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002724
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002725 if (ds.options_->telephony_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002726 ds.base_name_ += "-telephony";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002727 } else if (ds.options_->wifi_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002728 ds.base_name_ += "-wifi";
2729 }
2730
Paul Chang0d2aad72020-02-13 20:04:03 +08002731 if (ds.options_->do_screenshot) {
Nandana Dutt9d17b942020-03-26 10:02:59 +00002732 ds.screenshot_path_ = ds.GetPath(ds.CalledByApi() ? "-png.tmp" : ".png");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002733 }
2734 ds.tmp_path_ = ds.GetPath(".tmp");
2735 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2736
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01002737 std::string destination = ds.CalledByApi()
Nandana Dutt54dbd672019-01-11 12:58:05 +00002738 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
Nandana Dutt9a76d202019-01-21 15:56:48 +00002739 : ds.bugreport_internal_dir_.c_str();
Nandana Dutt4be45d12018-09-26 15:04:23 +01002740 MYLOGD(
Nandana Dutt235c6672019-11-14 15:22:32 +00002741 "Bugreport dir: [%s] "
2742 "Base name: [%s] "
2743 "Suffix: [%s] "
2744 "Log path: [%s] "
2745 "Temporary path: [%s] "
2746 "Screenshot path: [%s]\n",
Nandana Dutt9a76d202019-01-21 15:56:48 +00002747 destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2748 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002749
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002750 ds.path_ = ds.GetPath(ds.CalledByApi() ? "-zip.tmp" : ".zip");
2751 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2752 create_parent_dirs(ds.path_.c_str());
2753 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2754 if (ds.zip_file == nullptr) {
2755 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2756 return false;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002757 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002758 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2759 ds.AddTextZipEntry("version.txt", ds.version_);
2760 return true;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002761}
2762
2763/*
Abhijeet Kaure370d682019-10-01 16:49:30 +01002764 * Finalizes writing to the file by zipping the tmp file to the final location,
Nandana Dutt4be45d12018-09-26 15:04:23 +01002765 * printing zipped file status, etc.
2766 */
2767static void FinalizeFile() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002768 bool do_text_file = !ds.FinishZipFile();
2769 if (do_text_file) {
2770 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002771 }
mhasank2d75c442020-06-11 15:05:25 -07002772
2773 std::string final_path = ds.path_;
2774 if (ds.options_->OutputToCustomFile()) {
mhasank3a4cfb42020-06-15 18:06:43 -07002775 final_path = ds.GetPath(ds.options_->out_dir, ".zip");
mhasank2d75c442020-06-11 15:05:25 -07002776 android::os::CopyFileToFile(ds.path_, final_path);
2777 }
2778
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002779 if (ds.options_->stream_to_socket) {
2780 android::os::CopyFileToFd(ds.path_, ds.control_socket_fd_);
2781 } else if (ds.options_->progress_updates_to_socket) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002782 if (do_text_file) {
2783 dprintf(ds.control_socket_fd_,
2784 "FAIL:could not create zip file, check %s "
2785 "for more details\n",
2786 ds.log_path_.c_str());
2787 } else {
mhasank2d75c442020-06-11 15:05:25 -07002788 dprintf(ds.control_socket_fd_, "OK:%s\n", final_path.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002789 }
2790 }
2791}
2792
Nandana Dutt4be45d12018-09-26 15:04:23 +01002793
Nandana Dutt58d72e22018-11-16 10:30:48 +00002794static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2795 switch (mode) {
2796 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2797 return "BUGREPORT_FULL";
2798 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2799 return "BUGREPORT_INTERACTIVE";
2800 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2801 return "BUGREPORT_REMOTE";
2802 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2803 return "BUGREPORT_WEAR";
2804 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2805 return "BUGREPORT_TELEPHONY";
2806 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2807 return "BUGREPORT_WIFI";
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002808 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2809 return "BUGREPORT_DEFAULT";
Nandana Dutt58d72e22018-11-16 10:30:48 +00002810 }
2811}
2812
Steven Leeb573eb82022-11-29 22:31:35 +08002813static bool IsConsentlessBugreportAllowed(const Dumpstate::DumpOptions& options) {
2814 // only BUGREPORT_TELEPHONY does not allow using consentless bugreport
2815 return !options.telephony_only;
2816}
2817
Paul Changf59c2b72020-03-10 02:08:55 +08002818static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options,
2819 bool is_screenshot_requested) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002820 // Modify com.android.shell.BugreportProgressService#isDefaultScreenshotRequired as well for
2821 // default system screenshots.
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002822 options->bugreport_mode = mode;
2823 options->bugreport_mode_string = ModeToString(mode);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002824 switch (mode) {
2825 case Dumpstate::BugreportMode::BUGREPORT_FULL:
Paul Changf59c2b72020-03-10 02:08:55 +08002826 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002827 break;
2828 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002829 // Currently, the dumpstate binder is only used by Shell to update progress.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002830 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002831 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002832 break;
2833 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002834 options->do_vibrate = false;
2835 options->is_remote_mode = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002836 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002837 break;
2838 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
Robert Ginda55ecebd2023-04-03 22:53:13 +00002839 options->do_vibrate = false;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002840 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002841 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002842 break;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002843 // TODO(b/148168577) rename TELEPHONY everywhere to CONNECTIVITY.
Nandana Dutt58d72e22018-11-16 10:30:48 +00002844 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002845 options->telephony_only = true;
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002846 options->do_progress_updates = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002847 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002848 break;
2849 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002850 options->wifi_only = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002851 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002852 break;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002853 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2854 break;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002855 }
2856}
2857
Nandana Dutt58d72e22018-11-16 10:30:48 +00002858static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
Nandana Dutt235c6672019-11-14 15:22:32 +00002859 MYLOGI(
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002860 "do_vibrate: %d stream_to_socket: %d progress_updates_to_socket: %d do_screenshot: %d "
Rhed Jao25f50e02020-08-20 00:10:32 +08002861 "is_remote_mode: %d show_header_only: %d telephony_only: %d "
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002862 "wifi_only: %d do_progress_updates: %d fd: %d bugreport_mode: %s "
mhasankd451a472020-05-26 18:02:39 -07002863 "limited_only: %d args: %s\n",
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002864 options.do_vibrate, options.stream_to_socket, options.progress_updates_to_socket,
Paul Chang0d2aad72020-02-13 20:04:03 +08002865 options.do_screenshot, options.is_remote_mode, options.show_header_only,
Rhed Jao25f50e02020-08-20 00:10:32 +08002866 options.telephony_only, options.wifi_only,
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002867 options.do_progress_updates, options.bugreport_fd.get(),
2868 options.bugreport_mode_string.c_str(),
2869 options.limited_only, options.args.c_str());
Nandana Dutt58d72e22018-11-16 10:30:48 +00002870}
2871
Nandana Dutt54dbd672019-01-11 12:58:05 +00002872void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
Kean Mariotti306633e2022-09-05 16:30:47 +00002873 int bugreport_flags,
Nandana Dutt54dbd672019-01-11 12:58:05 +00002874 const android::base::unique_fd& bugreport_fd_in,
Paul Changf59c2b72020-03-10 02:08:55 +08002875 const android::base::unique_fd& screenshot_fd_in,
2876 bool is_screenshot_requested) {
Kean Mariotti306633e2022-09-05 16:30:47 +00002877 this->use_predumped_ui_data = bugreport_flags & BugreportFlag::BUGREPORT_USE_PREDUMPED_UI_DATA;
Gavin Corkerya44686c2022-11-23 18:16:51 +00002878 this->is_consent_deferred = bugreport_flags & BugreportFlag::BUGREPORT_FLAG_DEFER_CONSENT;
Nandana Dutt54dbd672019-01-11 12:58:05 +00002879 // Duplicate the fds because the passed in fds don't outlive the binder transaction.
Todd Frederick621533f2022-03-26 02:54:17 +00002880 bugreport_fd.reset(fcntl(bugreport_fd_in.get(), F_DUPFD_CLOEXEC, 0));
2881 screenshot_fd.reset(fcntl(screenshot_fd_in.get(), F_DUPFD_CLOEXEC, 0));
Nandana Dutt58d72e22018-11-16 10:30:48 +00002882
Paul Changf59c2b72020-03-10 02:08:55 +08002883 SetOptionsFromMode(bugreport_mode, this, is_screenshot_requested);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002884}
2885
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002886Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
2887 RunStatus status = RunStatus::OK;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002888 int c;
mhasankd451a472020-05-26 18:02:39 -07002889 while ((c = getopt(argc, argv, "dho:svqzpLPBRSV:w")) != -1) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002890 switch (c) {
2891 // clang-format off
mhasank3a4cfb42020-06-15 18:06:43 -07002892 case 'o': out_dir = optarg; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002893 case 's': stream_to_socket = true; break;
2894 case 'S': progress_updates_to_socket = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002895 case 'v': show_header_only = true; break;
2896 case 'q': do_vibrate = false; break;
Paul Chang0d2aad72020-02-13 20:04:03 +08002897 case 'p': do_screenshot = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002898 case 'P': do_progress_updates = true; break;
2899 case 'R': is_remote_mode = true; break;
mhasankd451a472020-05-26 18:02:39 -07002900 case 'L': limited_only = true; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002901 case 'V':
2902 case 'd':
2903 case 'z':
2904 // compatibility no-op
2905 break;
Nandana Dutt235864b2019-01-22 12:10:16 +00002906 case 'w':
2907 // This was already processed
2908 break;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002909 case 'h':
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002910 status = RunStatus::HELP;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002911 break;
2912 default:
2913 fprintf(stderr, "Invalid option: %c\n", c);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002914 status = RunStatus::INVALID_INPUT;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002915 break;
2916 // clang-format on
2917 }
2918 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08002919
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002920 for (int i = 0; i < argc; i++) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002921 args += argv[i];
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002922 if (i < argc - 1) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002923 args += " ";
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002924 }
2925 }
2926
2927 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
2928 optind = 1;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002929
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002930 return status;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002931}
2932
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002933bool Dumpstate::DumpOptions::ValidateOptions() const {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002934 if (bugreport_fd.get() != -1 && stream_to_socket) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002935 return false;
2936 }
2937
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002938 if ((progress_updates_to_socket || do_progress_updates) && stream_to_socket) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002939 return false;
2940 }
2941
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002942 if (is_remote_mode && (do_progress_updates || stream_to_socket)) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002943 return false;
2944 }
2945 return true;
2946}
2947
Nandana Dutt197661d2018-11-16 16:40:21 +00002948void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
2949 options_ = std::move(options);
2950}
2951
Abhijeet Kaura407fb82020-03-27 12:51:12 +00002952void Dumpstate::Initialize() {
2953 /* gets the sequential id */
2954 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
2955 id_ = ++last_id;
2956 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
2957}
2958
Nandana Duttd2f5f082019-01-18 17:13:52 +00002959Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
2960 Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
Gavin Corkerya44686c2022-11-23 18:16:51 +00002961 HandleRunStatus(status);
2962 return status;
2963}
2964
2965Dumpstate::RunStatus Dumpstate::Retrieve(int32_t calling_uid, const std::string& calling_package) {
2966 Dumpstate::RunStatus status = RetrieveInternal(calling_uid, calling_package);
2967 HandleRunStatus(status);
2968 return status;
2969}
2970
2971Dumpstate::RunStatus Dumpstate::RetrieveInternal(int32_t calling_uid,
2972 const std::string& calling_package) {
2973 consent_callback_ = new ConsentCallback();
2974 const String16 incidentcompanion("incidentcompanion");
2975 sp<android::IBinder> ics(
2976 defaultServiceManager()->checkService(incidentcompanion));
2977 android::String16 package(calling_package.c_str());
2978 if (ics != nullptr) {
2979 MYLOGD("Checking user consent via incidentcompanion service\n");
2980 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
2981 calling_uid, package, String16(), String16(),
2982 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
2983 } else {
2984 MYLOGD(
2985 "Unable to check user consent; incidentcompanion service unavailable\n");
2986 return RunStatus::USER_CONSENT_TIMED_OUT;
2987 }
2988 UserConsentResult consent_result = consent_callback_->getResult();
2989 int timeout_ms = 30 * 1000;
2990 while (consent_result == UserConsentResult::UNAVAILABLE &&
2991 consent_callback_->getElapsedTimeMs() < timeout_ms) {
2992 sleep(1);
2993 consent_result = consent_callback_->getResult();
2994 }
2995 if (consent_result == UserConsentResult::DENIED) {
2996 return RunStatus::USER_CONSENT_DENIED;
2997 }
2998 if (consent_result == UserConsentResult::UNAVAILABLE) {
2999 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3000 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3001 consent_callback_.get());
3002 return RunStatus::USER_CONSENT_TIMED_OUT;
3003 }
3004
3005 bool copy_succeeded =
3006 android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
3007 if (copy_succeeded) {
3008 android::os::UnlinkAndLogOnError(path_);
3009 }
3010 return copy_succeeded ? Dumpstate::RunStatus::OK
3011 : Dumpstate::RunStatus::ERROR;
3012}
3013
3014void Dumpstate::HandleRunStatus(Dumpstate::RunStatus status) {
3015 if (listener_ != nullptr) {
Nandana Duttbabf6c72019-01-15 14:11:12 +00003016 switch (status) {
3017 case Dumpstate::RunStatus::OK:
Gavin Corkerya44686c2022-11-23 18:16:51 +00003018 listener_->onFinished(path_.c_str());
Nandana Duttbabf6c72019-01-15 14:11:12 +00003019 break;
3020 case Dumpstate::RunStatus::HELP:
3021 break;
3022 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003023 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00003024 break;
3025 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003026 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
3027 break;
3028 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3029 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
3030 break;
3031 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
3032 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00003033 break;
3034 }
3035 }
Nandana Duttbabf6c72019-01-15 14:11:12 +00003036}
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003037void Dumpstate::Cancel() {
3038 CleanupTmpFiles();
3039 android::os::UnlinkAndLogOnError(log_path_);
3040 for (int i = 0; i < NUM_OF_DUMPS; i++) {
3041 android::os::UnlinkAndLogOnError(ds.bugreport_internal_dir_ + "/" +
3042 kDumpstateBoardFiles[i]);
3043 }
3044 tombstone_data_.clear();
3045 anr_data_.clear();
Woody Lin20767a92022-11-29 15:50:24 +08003046 shutdown_checkpoints_.clear();
Rhed Jao0daac912020-08-21 14:48:20 +08003047
3048 // Instead of shutdown the pool, we delete temporary files directly since
3049 // shutdown blocking the call.
3050 if (dump_pool_) {
3051 dump_pool_->deleteTempFiles();
3052 }
3053 if (zip_entry_tasks_) {
3054 zip_entry_tasks_->run(/*do_cancel =*/ true);
3055 }
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003056}
3057
Kean Mariotti306633e2022-09-05 16:30:47 +00003058void Dumpstate::PreDumpUiData() {
3059 MaybeSnapshotUiTraces();
3060}
3061
Nandana Dutt979388e2018-11-30 16:48:55 +00003062/*
3063 * Dumps relevant information to a bugreport based on the given options.
3064 *
3065 * The bugreport can be dumped to a file or streamed to a socket.
3066 *
3067 * How dumping to file works:
3068 * stdout is redirected to a temporary file. This will later become the main bugreport entry.
3069 * stderr is redirected a log file.
3070 *
3071 * The temporary bugreport is then populated via printfs, dumping contents of files and
3072 * output of commands to stdout.
3073 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003074 * A bunch of other files and dumps are added to the zip archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00003075 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003076 * The temporary bugreport file and the log file also get added to the archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00003077 *
mhasank2d75c442020-06-11 15:05:25 -07003078 * Bugreports are first generated in a local directory and later copied to the caller's fd
3079 * or directory if supplied.
Nandana Dutt979388e2018-11-30 16:48:55 +00003080 */
Nandana Duttd2f5f082019-01-18 17:13:52 +00003081Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
3082 const std::string& calling_package) {
Rhed Jao5377d792020-07-16 17:37:39 +08003083 DurationReporter duration_reporter("RUN INTERNAL", /* logcat_only = */true);
Nandana Dutt979388e2018-11-30 16:48:55 +00003084 LogDumpOptions(*options_);
Nandana Dutt197661d2018-11-16 16:40:21 +00003085 if (!options_->ValidateOptions()) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00003086 MYLOGE("Invalid options specified\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003087 return RunStatus::INVALID_INPUT;
3088 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003089 /* set as high priority, and protect from OOM killer */
3090 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003091
Felipe Lemed071c682016-10-20 16:48:00 -07003092 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07003093 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003094 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003095 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003096 } else {
3097 /* fallback to kernels <= 2.6.35 */
3098 oom_adj = fopen("/proc/self/oom_adj", "we");
3099 if (oom_adj) {
3100 fputs("-17", oom_adj);
3101 fclose(oom_adj);
3102 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003103 }
3104
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003105 if (version_ == VERSION_DEFAULT) {
3106 version_ = VERSION_CURRENT;
Michal Karpinski4db754f2015-12-11 18:04:32 +00003107 }
3108
Chris Morin5a50d482022-02-01 17:41:18 -08003109 if (version_ != VERSION_CURRENT) {
3110 MYLOGE("invalid version requested ('%s'); supported values are: ('%s', '%s')\n",
3111 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003112 return RunStatus::INVALID_INPUT;
Felipe Lemed071c682016-10-20 16:48:00 -07003113 }
3114
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003115 if (options_->show_header_only) {
3116 PrintHeader();
3117 return RunStatus::OK;
Felipe Lemed071c682016-10-20 16:48:00 -07003118 }
3119
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003120 MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n",
3121 calling_uid, calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003122
Felipe Leme7447d7c2016-11-03 18:12:22 -07003123 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003124 std::string stats_path =
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003125 android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003126 progress_.reset(new Progress(stats_path));
Felipe Leme7447d7c2016-11-03 18:12:22 -07003127
Sahana Raof35ed432019-07-12 10:47:52 +01003128 if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
3129 MYLOGE("Failed to acquire wake lock: %s\n", strerror(errno));
3130 } else {
3131 // Wake lock will be released automatically on process death
3132 MYLOGD("Wake lock acquired.\n");
3133 }
3134
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08003135 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07003136
Felipe Lemef0292972016-11-22 13:57:05 -08003137 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07003138 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
3139 }
3140
Kevin Jeonfa64e642023-07-27 11:36:41 -04003141 if (PropertiesHelper::IsStrictRun()) {
3142 MYLOGI(
3143 "Running on strict-run mode, which has shorter timeouts "
3144 "(to disable, call 'setprop dumpstate.strict_run false')\n");
3145 }
3146
Nandana Dutt235c6672019-11-14 15:22:32 +00003147 MYLOGI("dumpstate info: id=%d, args='%s', bugreport_mode= %s bugreport format version: %s\n",
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00003148 id_, options_->args.c_str(), options_->bugreport_mode_string.c_str(), version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08003149
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003150 do_early_screenshot_ = options_->do_progress_updates;
Felipe Lemee338bf62015-12-07 14:03:50 -08003151
Christopher Ferrised9354f2014-10-01 17:35:01 -07003152 // If we are going to use a socket, do it as early as possible
3153 // to avoid timeouts from bugreport.
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003154 if (options_->stream_to_socket || options_->progress_updates_to_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07003155 MYLOGD("Opening control socket\n");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003156 control_socket_fd_ = open_socket_fn_("dumpstate");
Nandana Dutta344cb62019-02-22 15:12:35 +00003157 if (control_socket_fd_ == -1) {
3158 return ERROR;
3159 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003160 if (options_->progress_updates_to_socket) {
3161 options_->do_progress_updates = 1;
3162 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07003163 }
3164
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003165 if (!PrepareToWriteToFile()) {
3166 return ERROR;
3167 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08003168
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003169 // Interactive, wear & telephony modes are default to true.
3170 // and may enable from cli option or when using control socket
3171 if (options_->do_progress_updates) {
3172 // clang-format off
3173 std::vector<std::string> am_args = {
3174 "--receiver-permission", "android.permission.DUMP",
3175 };
3176 // clang-format on
3177 // Send STARTED broadcast for apps that listen to bugreport generation events
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003178 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED",
3179 am_args, multiuser_get_user_id(calling_uid));
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003180 if (options_->progress_updates_to_socket) {
3181 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08003182 }
3183 }
3184
Nick Kralevichf3599b32016-01-25 15:05:16 -08003185 /* read /proc/cmdline before dropping root */
3186 FILE *cmdline = fopen("/proc/cmdline", "re");
3187 if (cmdline) {
3188 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
3189 fclose(cmdline);
3190 }
3191
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003192 if (options_->do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08003193 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05003194 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003195
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003196 if (zip_file != nullptr) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003197 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
3198 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003199 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08003200 }
3201 }
3202
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003203 int dup_stdout_fd;
3204 int dup_stderr_fd;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003205 // Redirect stderr to log_path_ for debugging.
3206 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
3207 if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
3208 return ERROR;
3209 }
3210 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
3211 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
3212 strerror(errno));
3213 }
Nandana Dutt979388e2018-11-30 16:48:55 +00003214
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003215 // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
3216 // moved into zip file later, if zipping.
3217 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
3218 // TODO: why not write to a file instead of stdout to overcome this problem?
3219 /* TODO: rather than generating a text file now and zipping it later,
3220 it would be more efficient to redirect stdout to the zip entry
3221 directly, but the libziparchive doesn't support that option yet. */
3222 if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
3223 return ERROR;
3224 }
3225 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
3226 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
3227 tmp_path_.c_str(), strerror(errno));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003228 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08003229
3230 // Don't buffer stdout
3231 setvbuf(stdout, nullptr, _IONBF, 0);
3232
Rhed Jao5377d792020-07-16 17:37:39 +08003233 // Enable the parallel run if the client requests to output to a file.
3234 EnableParallelRunIfNeeded();
3235 // Using scope guard to make sure the dump pool can be shut down correctly.
3236 auto scope_guard_to_shutdown_pool = android::base::make_scope_guard([=]() {
3237 ShutdownDumpPool();
3238 });
3239
Felipe Leme608385d2016-02-01 10:35:38 -08003240 // NOTE: there should be no stdout output until now, otherwise it would break the header.
3241 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08003242 // duration is logged into MYLOG instead.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003243 PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003244
Gavin Corkery6968f552020-11-22 18:09:05 +00003245 bool is_dumpstate_restricted = options_->telephony_only
3246 || options_->wifi_only
3247 || options_->limited_only;
3248 if (!is_dumpstate_restricted) {
Paul Chang0d2aad72020-02-13 20:04:03 +08003249 // Invoke critical dumpsys first to preserve system state, before doing anything else.
Jichao Lie89d9c12019-11-21 19:02:51 -08003250 RunDumpsysCritical();
Gavin Corkery6968f552020-11-22 18:09:05 +00003251 }
3252 MaybeTakeEarlyScreenshot();
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003253
3254 if (!is_dumpstate_restricted) {
3255 // Snapshot the system trace now (if running) to avoid that dumpstate's
3256 // own activity pushes out interesting data from the trace ring buffer.
3257 // The trace file is added to the zip by MaybeAddSystemTraceToZip().
3258 MaybeSnapshotSystemTrace();
Yohei Yukawa95305b32021-03-09 07:54:27 -08003259
Kean Mariotti306633e2022-09-05 16:30:47 +00003260 // Snapshot the UI traces now (if running).
3261 // The trace files will be added to bugreport later.
3262 MaybeSnapshotUiTraces();
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003263 }
Gavin Corkery6968f552020-11-22 18:09:05 +00003264 onUiIntensiveBugreportDumpsFinished(calling_uid);
3265 MaybeCheckUserConsent(calling_uid, calling_package);
3266 if (options_->telephony_only) {
3267 DumpstateTelephonyOnly(calling_package);
3268 } else if (options_->wifi_only) {
3269 DumpstateWifiOnly();
3270 } else if (options_->limited_only) {
3271 DumpstateLimitedOnly();
3272 } else {
Nandana Dutt4be45d12018-09-26 15:04:23 +01003273 // Dump state for the default case. This also drops root.
Jichao Lie89d9c12019-11-21 19:02:51 -08003274 RunStatus s = DumpstateDefaultAfterCritical();
Nandana Dutt5c390032019-03-12 10:52:56 +00003275 if (s != RunStatus::OK) {
Nandana Duttaac6f582019-07-26 14:32:47 +01003276 if (s == RunStatus::USER_CONSENT_DENIED) {
Nandana Dutt5c390032019-03-12 10:52:56 +00003277 HandleUserConsentDenied();
3278 }
3279 return s;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08003280 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07003281 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07003282
Felipe Leme55b42a62015-11-10 17:39:08 -08003283 /* close output if needed */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003284 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003285
Abhijeet Kaure370d682019-10-01 16:49:30 +01003286 // Zip the (now complete) .tmp file within the internal directory.
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003287 ATRACE_BEGIN("FinalizeFile");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003288 FinalizeFile();
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003289 ATRACE_END();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003290
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003291 // Share the final file with the caller if the user has consented or Shell is the caller.
Nandana Duttd2f5f082019-01-18 17:13:52 +00003292 Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
Gavin Corkerya44686c2022-11-23 18:16:51 +00003293 if (CalledByApi() && !options_->is_consent_deferred) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003294 status = CopyBugreportIfUserConsented(calling_uid);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003295 if (status != Dumpstate::RunStatus::OK &&
3296 status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3297 // Do an early return if there were errors. We make an exception for consent
3298 // timing out because it's possible the user got distracted. In this case the
3299 // bugreport is not shared but made available for manual retrieval.
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003300 MYLOGI("User denied consent. Returning\n");
Nandana Duttd2f5f082019-01-18 17:13:52 +00003301 return status;
3302 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003303 if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3304 MYLOGI(
3305 "Did not receive user consent yet."
3306 " Will not copy the bugreport artifacts to caller.\n");
Abhijeet Kaur57627412019-04-17 16:00:09 +01003307 const String16 incidentcompanion("incidentcompanion");
3308 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
3309 if (ics != nullptr) {
3310 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3311 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3312 consent_callback_.get());
3313 } else {
3314 MYLOGD("Unable to cancel user consent; incidentcompanion service unavailable\n");
3315 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003316 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003317 }
3318
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003319 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003320 if (options_->do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09003321 for (int i = 0; i < 3; i++) {
3322 Vibrate(75);
3323 usleep((75 + 50) * 1000);
3324 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003325 }
3326
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003327 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
3328 progress_->GetInitialMax());
3329 progress_->Save();
3330 MYLOGI("done (id %d)\n", id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003331
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003332 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08003333
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003334 if (control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07003335 MYLOGD("Closing control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003336 close(control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07003337 }
3338
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003339 tombstone_data_.clear();
3340 anr_data_.clear();
Woody Lin20767a92022-11-29 15:50:24 +08003341 shutdown_checkpoints_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01003342
Nandana Duttd2f5f082019-01-18 17:13:52 +00003343 return (consent_callback_ != nullptr &&
3344 consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
3345 ? USER_CONSENT_TIMED_OUT
3346 : RunStatus::OK;
3347}
3348
Paul Chang0d2aad72020-02-13 20:04:03 +08003349void Dumpstate::MaybeTakeEarlyScreenshot() {
3350 if (!options_->do_screenshot || !do_early_screenshot_) {
3351 return;
3352 }
3353
3354 TakeScreenshot();
3355}
3356
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003357void Dumpstate::MaybeSnapshotSystemTrace() {
3358 // If a background system trace is happening and is marked as "suitable for
3359 // bugreport" (i.e. bugreport_score > 0 in the trace config), this command
3360 // will stop it and serialize into SYSTEM_TRACE_SNAPSHOT. In the (likely)
3361 // case that no trace is ongoing, this command is a no-op.
3362 // Note: this should not be enqueued as we need to freeze the trace before
3363 // dumpstate starts. Otherwise the trace ring buffers will contain mostly
3364 // the dumpstate's own activity which is irrelevant.
3365 int res = RunCommand(
3366 "SERIALIZE PERFETTO TRACE",
3367 {"perfetto", "--save-for-bugreport"},
3368 CommandOptions::WithTimeout(10)
3369 .DropRoot()
3370 .CloseAllFileDescriptorsOnExec()
3371 .Build());
3372 has_system_trace_ = res == 0;
3373 // MaybeAddSystemTraceToZip() will take care of copying the trace in the zip
3374 // file in the later stages.
3375}
3376
Kean Mariotti306633e2022-09-05 16:30:47 +00003377void Dumpstate::MaybeSnapshotUiTraces() {
3378 if (PropertiesHelper::IsUserBuild() || options_->use_predumped_ui_data) {
3379 return;
3380 }
Hongwei Wang9ec5c252023-01-24 15:09:59 -08003381
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003382 const std::vector<std::vector<std::string>> dumpTracesForBugReportCommands = {
3383 {"dumpsys", "activity", "service", "SystemUIService", "WMShell", "protolog",
3384 "save-for-bugreport"},
3385 {"dumpsys", "activity", "service", "SystemUIService", "WMShell", "transitions", "tracing",
3386 "save-for-bugreport"},
3387 {"cmd", "input_method", "tracing", "save-for-bugreport"},
3388 {"cmd", "window", "tracing", "save-for-bugreport"},
3389 {"cmd", "window", "shell", "tracing", "save-for-bugreport"},
3390 };
Hongwei Wang39229132023-01-24 15:09:59 -08003391
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003392 for (const auto& command : dumpTracesForBugReportCommands) {
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003393 RunCommand(
3394 // Empty name because it's not intended to be classified as a bugreport section.
3395 // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003396 "", command,
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003397 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
3398 }
Kean Mariotti306633e2022-09-05 16:30:47 +00003399
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003400 // This command needs to be run as root
Kean Mariotti306633e2022-09-05 16:30:47 +00003401 static const auto SURFACEFLINGER_COMMAND_SAVE_ALL_TRACES = std::vector<std::string> {
3402 "service", "call", "SurfaceFlinger", "1042"
3403 };
3404 // Empty name because it's not intended to be classified as a bugreport section.
3405 // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
3406 RunCommand(
3407 "", SURFACEFLINGER_COMMAND_SAVE_ALL_TRACES,
3408 CommandOptions::WithTimeout(10).Always().AsRoot().RedirectStderr().Build());
3409}
3410
3411void Dumpstate::MaybePostProcessUiTraces() {
3412 if (PropertiesHelper::IsUserBuild()) {
3413 return;
3414 }
3415
3416 RunCommand(
3417 // Empty name because it's not intended to be classified as a bugreport section.
3418 // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
3419 "", {
3420 "/system/xbin/su", "system",
3421 "/system/bin/layertracegenerator",
3422 "/data/misc/wmtrace/transactions_trace.winscope",
3423 "/data/misc/wmtrace/layers_trace_from_transactions.winscope"
3424 },
3425 CommandOptions::WithTimeout(120).Always().RedirectStderr().Build());
3426}
3427
3428void Dumpstate::MaybeAddUiTracesToZip() {
3429 if (PropertiesHelper::IsUserBuild()) {
3430 return;
3431 }
3432
3433 ds.AddDir(WMTRACE_DATA_DIR, false);
Yohei Yukawa95305b32021-03-09 07:54:27 -08003434}
3435
Paul Changeb4b4642020-05-28 22:05:47 +08003436void Dumpstate::onUiIntensiveBugreportDumpsFinished(int32_t calling_uid) {
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003437 if (multiuser_get_app_id(calling_uid) == AID_SHELL || !CalledByApi()) {
Paul Changc490e662020-04-11 18:14:09 +08003438 return;
3439 }
3440 if (listener_ != nullptr) {
3441 // Let listener know ui intensive bugreport dumps are finished, then it can do event
3442 // handling if required.
Paul Changeb4b4642020-05-28 22:05:47 +08003443 listener_->onUiIntensiveBugreportDumpsFinished();
Paul Changc490e662020-04-11 18:14:09 +08003444 }
3445}
3446
Jichao Lie89d9c12019-11-21 19:02:51 -08003447void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) {
Gavin Corkerya44686c2022-11-23 18:16:51 +00003448 if (multiuser_get_app_id(calling_uid) == AID_SHELL ||
3449 !CalledByApi() || options_->is_consent_deferred) {
3450 // No need to get consent for shell triggered dumpstates, or not
3451 // through bugreporting API (i.e. no fd to copy back), or when consent
3452 // is deferred.
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003453 return;
3454 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003455 consent_callback_ = new ConsentCallback();
3456 const String16 incidentcompanion("incidentcompanion");
3457 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
Jichao Lie89d9c12019-11-21 19:02:51 -08003458 android::String16 package(calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003459 if (ics != nullptr) {
3460 MYLOGD("Checking user consent via incidentcompanion service\n");
Steven Leeb573eb82022-11-29 22:31:35 +08003461 int flags = 0x1; // IncidentManager.FLAG_CONFIRMATION_DIALOG
3462 if (IsConsentlessBugreportAllowed(*options_)) {
3463 flags |= 0x2; // IncidentManager.FLAG_ALLOW_CONSENTLESS_BUGREPORT
3464 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003465 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
Steven Leeb573eb82022-11-29 22:31:35 +08003466 calling_uid, package, String16(), String16(), flags, consent_callback_.get());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003467 } else {
3468 MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
3469 }
3470}
3471
Nandana Dutt5c390032019-03-12 10:52:56 +00003472bool Dumpstate::IsUserConsentDenied() const {
3473 return ds.consent_callback_ != nullptr &&
3474 ds.consent_callback_->getResult() == UserConsentResult::DENIED;
3475}
3476
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01003477bool Dumpstate::CalledByApi() const {
3478 return ds.options_->bugreport_fd.get() != -1 ? true : false;
3479}
3480
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003481void Dumpstate::CleanupTmpFiles() {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003482 android::os::UnlinkAndLogOnError(tmp_path_);
3483 android::os::UnlinkAndLogOnError(screenshot_path_);
3484 android::os::UnlinkAndLogOnError(path_);
Gavin Corkery789d7a52021-02-24 23:52:35 +00003485 if (dump_traces_path != nullptr) {
3486 android::os::UnlinkAndLogOnError(dump_traces_path);
3487 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003488}
3489
Rhed Jao5377d792020-07-16 17:37:39 +08003490void Dumpstate::EnableParallelRunIfNeeded() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003491 if (!PropertiesHelper::IsParallelRun()) {
Rhed Jao5377d792020-07-16 17:37:39 +08003492 return;
3493 }
3494 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003495 zip_entry_tasks_ = std::make_unique<TaskQueue>();
Rhed Jao5377d792020-07-16 17:37:39 +08003496}
3497
3498void Dumpstate::ShutdownDumpPool() {
3499 if (dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08003500 dump_pool_.reset();
Rhed Jao5377d792020-07-16 17:37:39 +08003501 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003502 if (zip_entry_tasks_) {
3503 zip_entry_tasks_->run(/* do_cancel = */true);
3504 zip_entry_tasks_ = nullptr;
3505 }
3506}
3507
3508void Dumpstate::EnqueueAddZipEntryAndCleanupIfNeeded(const std::string& entry_name,
3509 const std::string& entry_path) {
3510 auto func_add_zip_entry_and_cleanup = [=](bool task_cancelled) {
3511 if (!task_cancelled) {
3512 AddZipEntry(entry_name, entry_path);
3513 }
3514 android::os::UnlinkAndLogOnError(entry_path);
3515 };
3516 if (zip_entry_tasks_) {
3517 // Enqueues AddZipEntryAndCleanup function if the parallel run is enabled.
3518 zip_entry_tasks_->add(func_add_zip_entry_and_cleanup, _1);
3519 } else {
3520 // Invokes AddZipEntryAndCleanup immediately
3521 std::invoke(func_add_zip_entry_and_cleanup, /* task_cancelled = */false);
3522 }
Rhed Jao5377d792020-07-16 17:37:39 +08003523}
3524
Nandana Duttd2f5f082019-01-18 17:13:52 +00003525Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
3526 MYLOGD("User denied consent; deleting files and returning\n");
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003527 CleanupTmpFiles();
Nandana Duttd2f5f082019-01-18 17:13:52 +00003528 return USER_CONSENT_DENIED;
3529}
3530
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003531Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented(int32_t calling_uid) {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003532 // If the caller has asked to copy the bugreport over to their directory, we need explicit
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003533 // user consent (unless the caller is Shell).
3534 UserConsentResult consent_result;
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003535 if (multiuser_get_app_id(calling_uid) == AID_SHELL) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003536 consent_result = UserConsentResult::APPROVED;
3537 } else {
3538 consent_result = consent_callback_->getResult();
3539 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003540 if (consent_result == UserConsentResult::UNAVAILABLE) {
3541 // User has not responded yet.
3542 uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
Hunter Knepshield70610fa2020-01-03 15:27:33 -08003543 // Telephony is a fast report type, particularly on user builds where information may be
3544 // more aggressively limited. To give the user time to read the consent dialog, increase the
3545 // timeout.
3546 uint64_t timeout_ms = options_->telephony_only ? TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS
3547 : USER_CONSENT_TIMEOUT_MS;
3548 if (elapsed_ms < timeout_ms) {
3549 uint delay_seconds = (timeout_ms - elapsed_ms) / 1000;
Nandana Duttd2f5f082019-01-18 17:13:52 +00003550 MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
3551 sleep(delay_seconds);
3552 }
3553 consent_result = consent_callback_->getResult();
3554 }
3555 if (consent_result == UserConsentResult::DENIED) {
3556 // User has explicitly denied sharing with the app. To be safe delete the
3557 // internal bugreport & tmp files.
3558 return HandleUserConsentDenied();
3559 }
3560 if (consent_result == UserConsentResult::APPROVED) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00003561 bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
3562 if (copy_succeeded) {
3563 android::os::UnlinkAndLogOnError(path_);
Abhijeet Kaur9ce94672020-04-01 17:22:36 +01003564 if (options_->do_screenshot &&
3565 options_->screenshot_fd.get() != -1 &&
3566 !options_->is_screenshot_copied) {
3567 copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
3568 options_->screenshot_fd.get());
3569 options_->is_screenshot_copied = copy_succeeded;
3570 if (copy_succeeded) {
3571 android::os::UnlinkAndLogOnError(screenshot_path_);
3572 }
3573 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003574 }
3575 return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
3576 } else if (consent_result == UserConsentResult::UNAVAILABLE) {
3577 // consent_result is still UNAVAILABLE. The user has likely not responded yet.
3578 // Since we do not have user consent to share the bugreport it does not get
3579 // copied over to the calling app but remains in the internal directory from
3580 // where the user can manually pull it.
Paul Changce644212021-05-11 16:06:45 +08003581 std::string final_path = GetPath(".zip");
3582 bool copy_succeeded = android::os::CopyFileToFile(path_, final_path);
3583 if (copy_succeeded) {
3584 android::os::UnlinkAndLogOnError(path_);
3585 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003586 return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
3587 }
3588 // Unknown result; must be a programming error.
3589 MYLOGE("Unknown user consent result:%d\n", consent_result);
3590 return Dumpstate::RunStatus::ERROR;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003591}
3592
Nandana Duttf02564e2019-02-15 15:24:24 +00003593Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003594 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
3595 Dumpstate::RunStatus status = options->Initialize(argc, argv);
3596 if (status == Dumpstate::RunStatus::OK) {
Nandana Duttf02564e2019-02-15 15:24:24 +00003597 SetOptions(std::move(options));
Nandana Duttd2f5f082019-01-18 17:13:52 +00003598 // When directly running dumpstate binary, the output is not expected to be written
3599 // to any external file descriptor.
Nandana Duttf02564e2019-02-15 15:24:24 +00003600 assert(options_->bugreport_fd.get() == -1);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003601
3602 // calling_uid and calling_package are for user consent to share the bugreport with
Abhijeet Kaura407fb82020-03-27 12:51:12 +00003603 // an app; they are irrelevant here because bugreport is triggered via command line.
3604 // Update Last ID before calling Run().
3605 Initialize();
Nikhil Kumarb70622a2023-06-15 15:37:19 +01003606 status = Run(0 /* calling_uid */, "" /* calling_package */);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003607 }
Nandana Duttf02564e2019-02-15 15:24:24 +00003608 return status;
3609}
3610
3611/* Main entry point for dumpstate binary. */
3612int run_main(int argc, char* argv[]) {
3613 Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003614
3615 switch (status) {
3616 case Dumpstate::RunStatus::OK:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003617 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003618 case Dumpstate::RunStatus::HELP:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003619 ShowUsage();
3620 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003621 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003622 fprintf(stderr, "Invalid combination of args\n");
3623 ShowUsage();
3624 exit(1);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003625 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003626 FALLTHROUGH_INTENDED;
3627 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3628 FALLTHROUGH_INTENDED;
3629 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003630 exit(2);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003631 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003632}
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003633
3634// TODO(111441001): Default DumpOptions to sensible values.
3635Dumpstate::Dumpstate(const std::string& version)
3636 : pid_(getpid()),
3637 options_(new Dumpstate::DumpOptions()),
Nandana Dutt402a8392019-06-14 14:25:13 +01003638 last_reported_percent_progress_(0),
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003639 version_(version),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003640 now_(time(nullptr)),
3641 open_socket_fn_(open_socket) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003642}
3643
3644Dumpstate& Dumpstate::GetInstance() {
3645 static Dumpstate singleton_(android::base::GetProperty("dumpstate.version", VERSION_CURRENT));
3646 return singleton_;
3647}
3648
Rhed Jao5377d792020-07-16 17:37:39 +08003649DurationReporter::DurationReporter(const std::string& title, bool logcat_only, bool verbose,
3650 int duration_fd) : title_(title), logcat_only_(logcat_only), verbose_(verbose),
3651 duration_fd_(duration_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003652 if (!title_.empty()) {
3653 started_ = Nanotime();
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003654 if (title_.find("SHOW MAP") == std::string::npos) {
3655 ATRACE_ASYNC_BEGIN(title_.c_str(), 0);
3656 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003657 }
3658}
3659
3660DurationReporter::~DurationReporter() {
3661 if (!title_.empty()) {
3662 float elapsed = (float)(Nanotime() - started_) / NANOS_PER_SEC;
chenqiwuaf8b2d92019-12-12 18:53:51 +08003663 if (elapsed >= .5f || verbose_) {
3664 MYLOGD("Duration of '%s': %.2fs\n", title_.c_str(), elapsed);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003665 }
chenqiwuaf8b2d92019-12-12 18:53:51 +08003666 if (!logcat_only_) {
3667 // Use "Yoda grammar" to make it easier to grep|sort sections.
Rhed Jao5377d792020-07-16 17:37:39 +08003668 dprintf(duration_fd_, "------ %.3fs was the duration of '%s' ------\n",
3669 elapsed, title_.c_str());
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003670 }
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003671 if (title_.find("SHOW MAP") == std::string::npos) {
3672 ATRACE_ASYNC_END(title_.c_str(), 0);
3673 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003674 }
3675}
3676
3677const int32_t Progress::kDefaultMax = 5000;
3678
3679Progress::Progress(const std::string& path) : Progress(Progress::kDefaultMax, 1.1, path) {
3680}
3681
3682Progress::Progress(int32_t initial_max, int32_t progress, float growth_factor)
3683 : Progress(initial_max, growth_factor, "") {
3684 progress_ = progress;
3685}
3686
3687Progress::Progress(int32_t initial_max, float growth_factor, const std::string& path)
3688 : initial_max_(initial_max),
3689 progress_(0),
3690 max_(initial_max),
3691 growth_factor_(growth_factor),
3692 n_runs_(0),
3693 average_max_(0),
3694 path_(path) {
3695 if (!path_.empty()) {
3696 Load();
3697 }
3698}
3699
3700void Progress::Load() {
3701 MYLOGD("Loading stats from %s\n", path_.c_str());
3702 std::string content;
3703 if (!android::base::ReadFileToString(path_, &content)) {
3704 MYLOGI("Could not read stats from %s; using max of %d\n", path_.c_str(), max_);
3705 return;
3706 }
3707 if (content.empty()) {
3708 MYLOGE("No stats (empty file) on %s; using max of %d\n", path_.c_str(), max_);
3709 return;
3710 }
3711 std::vector<std::string> lines = android::base::Split(content, "\n");
3712
3713 if (lines.size() < 1) {
3714 MYLOGE("Invalid stats on file %s: not enough lines (%d). Using max of %d\n", path_.c_str(),
3715 (int)lines.size(), max_);
3716 return;
3717 }
3718 char* ptr;
3719 n_runs_ = strtol(lines[0].c_str(), &ptr, 10);
3720 average_max_ = strtol(ptr, nullptr, 10);
3721 if (n_runs_ <= 0 || average_max_ <= 0 || n_runs_ > STATS_MAX_N_RUNS ||
3722 average_max_ > STATS_MAX_AVERAGE) {
3723 MYLOGE("Invalid stats line on file %s: %s\n", path_.c_str(), lines[0].c_str());
3724 initial_max_ = Progress::kDefaultMax;
3725 } else {
3726 initial_max_ = average_max_;
3727 }
3728 max_ = initial_max_;
3729
3730 MYLOGI("Average max progress: %d in %d runs; estimated max: %d\n", average_max_, n_runs_, max_);
3731}
3732
3733void Progress::Save() {
3734 int32_t total = n_runs_ * average_max_ + progress_;
3735 int32_t runs = n_runs_ + 1;
3736 int32_t average = floor(((float)total) / runs);
3737 MYLOGI("Saving stats (total=%d, runs=%d, average=%d) on %s\n", total, runs, average,
3738 path_.c_str());
3739 if (path_.empty()) {
3740 return;
3741 }
3742
3743 std::string content = android::base::StringPrintf("%d %d\n", runs, average);
3744 if (!android::base::WriteStringToFile(content, path_)) {
3745 MYLOGE("Could not save stats on %s\n", path_.c_str());
3746 }
3747}
3748
3749int32_t Progress::Get() const {
3750 return progress_;
3751}
3752
3753bool Progress::Inc(int32_t delta_sec) {
3754 bool changed = false;
3755 if (delta_sec >= 0) {
3756 progress_ += delta_sec;
3757 if (progress_ > max_) {
3758 int32_t old_max = max_;
3759 max_ = floor((float)progress_ * growth_factor_);
3760 MYLOGD("Adjusting max progress from %d to %d\n", old_max, max_);
3761 changed = true;
3762 }
3763 }
3764 return changed;
3765}
3766
3767int32_t Progress::GetMax() const {
3768 return max_;
3769}
3770
3771int32_t Progress::GetInitialMax() const {
3772 return initial_max_;
3773}
3774
3775void Progress::Dump(int fd, const std::string& prefix) const {
3776 const char* pr = prefix.c_str();
3777 dprintf(fd, "%sprogress: %d\n", pr, progress_);
3778 dprintf(fd, "%smax: %d\n", pr, max_);
3779 dprintf(fd, "%sinitial_max: %d\n", pr, initial_max_);
3780 dprintf(fd, "%sgrowth_factor: %0.2f\n", pr, growth_factor_);
3781 dprintf(fd, "%spath: %s\n", pr, path_.c_str());
3782 dprintf(fd, "%sn_runs: %d\n", pr, n_runs_);
3783 dprintf(fd, "%saverage_max: %d\n", pr, average_max_);
3784}
3785
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003786std::string Dumpstate::GetPath(const std::string& suffix) const {
3787 return GetPath(bugreport_internal_dir_, suffix);
3788}
3789
3790std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
3791 return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
3792 name_.c_str(), suffix.c_str());
3793}
3794
3795void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
3796 progress_ = std::move(progress);
3797}
3798
3799void for_each_userid(void (*func)(int), const char *header) {
3800 std::string title = header == nullptr ? "for_each_userid" : android::base::StringPrintf(
3801 "for_each_userid(%s)", header);
3802 DurationReporter duration_reporter(title);
3803 if (PropertiesHelper::IsDryRun()) return;
3804
3805 DIR *d;
3806 struct dirent *de;
3807
3808 if (header) printf("\n------ %s ------\n", header);
3809 func(0);
3810
3811 if (!(d = opendir("/data/system/users"))) {
3812 printf("Failed to open /data/system/users (%s)\n", strerror(errno));
3813 return;
3814 }
3815
3816 while ((de = readdir(d))) {
3817 int userid;
3818 if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
3819 continue;
3820 }
3821 func(userid);
3822 }
3823
3824 closedir(d);
3825}
3826
3827static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
3828 DIR *d;
3829 struct dirent *de;
3830
3831 if (!(d = opendir("/proc"))) {
3832 printf("Failed to open /proc (%s)\n", strerror(errno));
3833 return;
3834 }
3835
3836 if (header) printf("\n------ %s ------\n", header);
3837 while ((de = readdir(d))) {
3838 if (ds.IsUserConsentDenied()) {
3839 MYLOGE(
3840 "Returning early because user denied consent to share bugreport with calling app.");
3841 closedir(d);
3842 return;
3843 }
3844 int pid;
3845 int fd;
3846 char cmdpath[255];
3847 char cmdline[255];
3848
3849 if (!(pid = atoi(de->d_name))) {
3850 continue;
3851 }
3852
3853 memset(cmdline, 0, sizeof(cmdline));
3854
3855 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
3856 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3857 TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
3858 close(fd);
3859 if (cmdline[0]) {
3860 helper(pid, cmdline, arg);
3861 continue;
3862 }
3863 }
3864
3865 // if no cmdline, a kernel thread has comm
3866 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
3867 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3868 TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
3869 close(fd);
3870 if (cmdline[1]) {
3871 cmdline[0] = '[';
3872 size_t len = strcspn(cmdline, "\f\b\r\n");
3873 cmdline[len] = ']';
3874 cmdline[len+1] = '\0';
3875 }
3876 }
3877 if (!cmdline[0]) {
3878 strcpy(cmdline, "N/A");
3879 }
3880 helper(pid, cmdline, arg);
3881 }
3882
3883 closedir(d);
3884}
3885
3886static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
3887 for_each_pid_func *func = (for_each_pid_func*) arg;
3888 func(pid, cmdline);
3889}
3890
3891void for_each_pid(for_each_pid_func func, const char *header) {
3892 std::string title = header == nullptr ? "for_each_pid"
3893 : android::base::StringPrintf("for_each_pid(%s)", header);
3894 DurationReporter duration_reporter(title);
3895 if (PropertiesHelper::IsDryRun()) return;
3896
3897 __for_each_pid(for_each_pid_helper, header, (void *) func);
3898}
3899
3900static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
3901 DIR *d;
3902 struct dirent *de;
3903 char taskpath[255];
3904 for_each_tid_func *func = (for_each_tid_func *) arg;
3905
3906 snprintf(taskpath, sizeof(taskpath), "/proc/%d/task", pid);
3907
3908 if (!(d = opendir(taskpath))) {
3909 printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
3910 return;
3911 }
3912
3913 func(pid, pid, cmdline);
3914
3915 while ((de = readdir(d))) {
3916 if (ds.IsUserConsentDenied()) {
3917 MYLOGE(
3918 "Returning early because user denied consent to share bugreport with calling app.");
3919 closedir(d);
3920 return;
3921 }
3922 int tid;
3923 int fd;
3924 char commpath[255];
3925 char comm[255];
3926
3927 if (!(tid = atoi(de->d_name))) {
3928 continue;
3929 }
3930
3931 if (tid == pid)
3932 continue;
3933
3934 snprintf(commpath, sizeof(commpath), "/proc/%d/comm", tid);
3935 memset(comm, 0, sizeof(comm));
3936 if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
3937 strcpy(comm, "N/A");
3938 } else {
3939 char *c;
3940 TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
3941 close(fd);
3942
3943 c = strrchr(comm, '\n');
3944 if (c) {
3945 *c = '\0';
3946 }
3947 }
3948 func(pid, tid, comm);
3949 }
3950
3951 closedir(d);
3952}
3953
3954void for_each_tid(for_each_tid_func func, const char *header) {
3955 std::string title = header == nullptr ? "for_each_tid"
3956 : android::base::StringPrintf("for_each_tid(%s)", header);
3957 DurationReporter duration_reporter(title);
3958
3959 if (PropertiesHelper::IsDryRun()) return;
3960
3961 __for_each_pid(for_each_tid_helper, header, (void *) func);
3962}
3963
3964void show_wchan(int pid, int tid, const char *name) {
3965 if (PropertiesHelper::IsDryRun()) return;
3966
3967 char path[255];
3968 char buffer[255];
3969 int fd, ret, save_errno;
3970 char name_buffer[255];
3971
3972 memset(buffer, 0, sizeof(buffer));
3973
3974 snprintf(path, sizeof(path), "/proc/%d/wchan", tid);
3975 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
3976 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
3977 return;
3978 }
3979
3980 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3981 save_errno = errno;
3982 close(fd);
3983
3984 if (ret < 0) {
3985 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
3986 return;
3987 }
3988
3989 snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
3990 pid == tid ? 0 : 3, "", name);
3991
3992 printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
3993
3994 return;
3995}
3996
3997// print time in centiseconds
3998static void snprcent(char *buffer, size_t len, size_t spc,
3999 unsigned long long time) {
4000 static long hz; // cache discovered hz
4001
4002 if (hz <= 0) {
4003 hz = sysconf(_SC_CLK_TCK);
4004 if (hz <= 0) {
4005 hz = 1000;
4006 }
4007 }
4008
4009 // convert to centiseconds
4010 time = (time * 100 + (hz / 2)) / hz;
4011
4012 char str[16];
4013
4014 snprintf(str, sizeof(str), " %llu.%02u",
4015 time / 100, (unsigned)(time % 100));
4016 size_t offset = strlen(buffer);
4017 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
4018 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
4019}
4020
4021// print permille as a percent
4022static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
4023 char str[16];
4024
4025 snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
4026 size_t offset = strlen(buffer);
4027 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
4028 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
4029}
4030
4031void show_showtime(int pid, const char *name) {
4032 if (PropertiesHelper::IsDryRun()) return;
4033
4034 char path[255];
4035 char buffer[1023];
4036 int fd, ret, save_errno;
4037
4038 memset(buffer, 0, sizeof(buffer));
4039
4040 snprintf(path, sizeof(path), "/proc/%d/stat", pid);
4041 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
4042 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
4043 return;
4044 }
4045
4046 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
4047 save_errno = errno;
4048 close(fd);
4049
4050 if (ret < 0) {
4051 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
4052 return;
4053 }
4054
4055 // field 14 is utime
4056 // field 15 is stime
4057 // field 42 is iotime
4058 unsigned long long utime = 0, stime = 0, iotime = 0;
4059 if (sscanf(buffer,
4060 "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
4061 "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
4062 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
4063 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
4064 &utime, &stime, &iotime) != 3) {
4065 return;
4066 }
4067
4068 unsigned long long total = utime + stime;
4069 if (!total) {
4070 return;
4071 }
4072
4073 unsigned permille = (iotime * 1000 + (total / 2)) / total;
4074 if (permille > 1000) {
4075 permille = 1000;
4076 }
4077
4078 // try to beautify and stabilize columns at <80 characters
4079 snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
4080 if ((name[0] != '[') || utime) {
4081 snprcent(buffer, sizeof(buffer), 57, utime);
4082 }
4083 snprcent(buffer, sizeof(buffer), 65, stime);
4084 if ((name[0] != '[') || iotime) {
4085 snprcent(buffer, sizeof(buffer), 73, iotime);
4086 }
4087 if (iotime) {
4088 snprdec(buffer, sizeof(buffer), 79, permille);
4089 }
4090 puts(buffer); // adds a trailing newline
4091
4092 return;
4093}
4094
4095void do_dmesg() {
4096 const char *title = "KERNEL LOG (dmesg)";
4097 DurationReporter duration_reporter(title);
4098 printf("------ %s ------\n", title);
4099
4100 if (PropertiesHelper::IsDryRun()) return;
4101
4102 /* Get size of kernel buffer */
4103 int size = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
4104 if (size <= 0) {
4105 printf("Unexpected klogctl return value: %d\n\n", size);
4106 return;
4107 }
4108 char *buf = (char *) malloc(size + 1);
4109 if (buf == nullptr) {
4110 printf("memory allocation failed\n\n");
4111 return;
4112 }
4113 int retval = klogctl(KLOG_READ_ALL, buf, size);
4114 if (retval < 0) {
4115 printf("klogctl failure\n\n");
4116 free(buf);
4117 return;
4118 }
4119 buf[retval] = '\0';
4120 printf("%s\n\n", buf);
4121 free(buf);
4122 return;
4123}
4124
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004125int Dumpstate::DumpFile(const std::string& title, const std::string& path) {
4126 DurationReporter duration_reporter(title);
4127
4128 int status = DumpFileToFd(STDOUT_FILENO, title, path);
4129
4130 UpdateProgress(WEIGHT_FILE);
4131
4132 return status;
4133}
4134
4135int read_file_as_long(const char *path, long int *output) {
4136 int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
4137 if (fd < 0) {
4138 int err = errno;
4139 MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
4140 return -1;
4141 }
4142 char buffer[50];
4143 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
4144 if (bytes_read == -1) {
4145 MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
4146 return -2;
4147 }
4148 if (bytes_read == 0) {
4149 MYLOGE("File %s is empty\n", path);
4150 return -3;
4151 }
4152 *output = atoi(buffer);
4153 return 0;
4154}
4155
4156/* calls skip to gate calling dump_from_fd recursively
4157 * in the specified directory. dump_from_fd defaults to
4158 * dump_file_from_fd above when set to NULL. skip defaults
4159 * to false when set to NULL. dump_from_fd will always be
4160 * called with title NULL.
4161 */
4162int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
4163 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4164 DurationReporter duration_reporter(title);
4165 DIR *dirp;
4166 struct dirent *d;
4167 char *newpath = nullptr;
4168 const char *slash = "/";
4169 int retval = 0;
4170
4171 if (!title.empty()) {
4172 printf("------ %s (%s) ------\n", title.c_str(), dir);
4173 }
4174 if (PropertiesHelper::IsDryRun()) return 0;
4175
4176 if (dir[strlen(dir) - 1] == '/') {
4177 ++slash;
4178 }
4179 dirp = opendir(dir);
4180 if (dirp == nullptr) {
4181 retval = -errno;
4182 MYLOGE("%s: %s\n", dir, strerror(errno));
4183 return retval;
4184 }
4185
4186 if (!dump_from_fd) {
4187 dump_from_fd = dump_file_from_fd;
4188 }
4189 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4190 if ((d->d_name[0] == '.')
4191 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4192 || (d->d_name[1] == '\0'))) {
4193 continue;
4194 }
4195 asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
4196 (d->d_type == DT_DIR) ? "/" : "");
4197 if (!newpath) {
4198 retval = -errno;
4199 continue;
4200 }
4201 if (skip && (*skip)(newpath)) {
4202 continue;
4203 }
4204 if (d->d_type == DT_DIR) {
4205 int ret = dump_files("", newpath, skip, dump_from_fd);
4206 if (ret < 0) {
4207 retval = ret;
4208 }
4209 continue;
4210 }
4211 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
4212 if (fd.get() < 0) {
4213 retval = -1;
4214 printf("*** %s: %s\n", newpath, strerror(errno));
4215 continue;
4216 }
4217 (*dump_from_fd)(nullptr, newpath, fd.get());
4218 }
4219 closedir(dirp);
4220 if (!title.empty()) {
4221 printf("\n");
4222 }
4223 return retval;
4224}
4225
4226/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
4227 * it's possible to avoid issues where opening the file itself can get
4228 * stuck.
4229 */
4230int dump_file_from_fd(const char *title, const char *path, int fd) {
4231 if (PropertiesHelper::IsDryRun()) return 0;
4232
4233 int flags = fcntl(fd, F_GETFL);
4234 if (flags == -1) {
4235 printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
4236 return -1;
4237 } else if (!(flags & O_NONBLOCK)) {
4238 printf("*** %s: fd must have O_NONBLOCK set.\n", path);
4239 return -1;
4240 }
4241 return DumpFileFromFdToFd(title, path, fd, STDOUT_FILENO, PropertiesHelper::IsDryRun());
4242}
4243
4244int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004245 const CommandOptions& options, bool verbose_duration, int out_fd) {
4246 DurationReporter duration_reporter(title, false /* logcat_only */,
4247 verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004248
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004249 int status = RunCommandToFd(out_fd, title, full_command, options);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004250
4251 /* TODO: for now we're simplifying the progress calculation by using the
4252 * timeout as the weight. It's a good approximation for most cases, except when calling dumpsys,
4253 * where its weight should be much higher proportionally to its timeout.
4254 * Ideally, it should use a options.EstimatedDuration() instead...*/
4255 UpdateProgress(options.Timeout());
4256
4257 return status;
4258}
4259
4260void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
Rhed Jaoe017f982020-07-21 17:58:41 +08004261 const CommandOptions& options, long dumpsysTimeoutMs, int out_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004262 long timeout_ms = dumpsysTimeoutMs > 0 ? dumpsysTimeoutMs : options.TimeoutInMs();
4263 std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-T", std::to_string(timeout_ms)};
4264 dumpsys.insert(dumpsys.end(), dumpsys_args.begin(), dumpsys_args.end());
Rhed Jaoe017f982020-07-21 17:58:41 +08004265 RunCommand(title, dumpsys, options, false, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004266}
4267
Dieter Hsu105ad0c2020-09-29 15:23:33 +08004268static int open_socket(const char* service) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004269 int s = android_get_control_socket(service);
4270 if (s < 0) {
4271 MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
4272 return -1;
4273 }
4274 fcntl(s, F_SETFD, FD_CLOEXEC);
4275
4276 // Set backlog to 0 to make sure that queue size will be minimum.
4277 // In Linux, because the minimum queue will be 1, connect() will be blocked
4278 // if the other clients already called connect() and the connection request was not accepted.
4279 if (listen(s, 0) < 0) {
4280 MYLOGE("listen(control socket): %s\n", strerror(errno));
4281 return -1;
4282 }
4283
4284 struct sockaddr addr;
4285 socklen_t alen = sizeof(addr);
Abhijeet Kaur2113cae2019-09-13 09:24:15 +01004286 int fd = accept4(s, &addr, &alen, SOCK_CLOEXEC);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004287
4288 // Close socket just after accept(), to make sure that connect() by client will get error
4289 // when the socket is used by the other services.
4290 // There is still a race condition possibility between accept and close, but there is no way
4291 // to close-on-accept atomically.
4292 // See detail; b/123306389#comment25
4293 close(s);
4294
4295 if (fd < 0) {
4296 MYLOGE("accept(control socket): %s\n", strerror(errno));
4297 return -1;
4298 }
4299
4300 return fd;
4301}
4302
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004303// TODO: should call is_valid_output_file and/or be merged into it.
4304void create_parent_dirs(const char *path) {
4305 char *chp = const_cast<char *> (path);
4306
4307 /* skip initial slash */
4308 if (chp[0] == '/')
4309 chp++;
4310
4311 /* create leading directories, if necessary */
4312 struct stat dir_stat;
4313 while (chp && chp[0]) {
4314 chp = strchr(chp, '/');
4315 if (chp) {
4316 *chp = 0;
4317 if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
4318 MYLOGI("Creating directory %s\n", path);
4319 if (mkdir(path, 0770)) { /* drwxrwx--- */
4320 MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
4321 } else if (chown(path, AID_SHELL, AID_SHELL)) {
4322 MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
4323 }
4324 }
4325 *chp++ = '/';
4326 }
4327 }
4328}
4329
4330bool _redirect_to_file(FILE* redirect, char* path, int truncate_flag) {
4331 create_parent_dirs(path);
4332
4333 int fd = TEMP_FAILURE_RETRY(open(path,
4334 O_WRONLY | O_CREAT | truncate_flag | O_CLOEXEC | O_NOFOLLOW,
4335 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
4336 if (fd < 0) {
4337 MYLOGE("%s: %s\n", path, strerror(errno));
4338 return false;
4339 }
4340
4341 TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
4342 close(fd);
4343 return true;
4344}
4345
4346bool redirect_to_file(FILE* redirect, char* path) {
4347 return _redirect_to_file(redirect, path, O_TRUNC);
4348}
4349
4350bool redirect_to_existing_file(FILE* redirect, char* path) {
4351 return _redirect_to_file(redirect, path, O_APPEND);
4352}
4353
4354void dump_route_tables() {
4355 DurationReporter duration_reporter("DUMP ROUTE TABLES");
4356 if (PropertiesHelper::IsDryRun()) return;
4357 const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
4358 ds.DumpFile("RT_TABLES", RT_TABLES_PATH);
4359 FILE* fp = fopen(RT_TABLES_PATH, "re");
4360 if (!fp) {
4361 printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
4362 return;
4363 }
4364 char table[16];
4365 // Each line has an integer (the table number), a space, and a string (the table name). We only
4366 // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
4367 // Add a fixed max limit so this doesn't go awry.
4368 for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
4369 RunCommand("ROUTE TABLE IPv4", {"ip", "-4", "route", "show", "table", table});
4370 RunCommand("ROUTE TABLE IPv6", {"ip", "-6", "route", "show", "table", table});
4371 }
4372 fclose(fp);
4373}
4374
Li Li830179f2022-01-04 12:53:29 -08004375void dump_frozen_cgroupfs(const char *dir, int level,
4376 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4377 DIR *dirp;
4378 struct dirent *d;
4379 char *newpath = nullptr;
4380
4381 dirp = opendir(dir);
4382 if (dirp == nullptr) {
4383 MYLOGE("%s: %s\n", dir, strerror(errno));
4384 return;
4385 }
4386
4387 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4388 if ((d->d_name[0] == '.')
4389 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4390 || (d->d_name[1] == '\0'))) {
4391 continue;
4392 }
4393 if (d->d_type == DT_DIR) {
4394 asprintf(&newpath, "%s/%s/", dir, d->d_name);
4395 if (!newpath) {
4396 continue;
4397 }
4398 if (level == 0 && !strncmp(d->d_name, "uid_", 4)) {
4399 dump_frozen_cgroupfs(newpath, 1, dump_from_fd);
4400 } else if (level == 1 && !strncmp(d->d_name, "pid_", 4)) {
4401 char *freezer = nullptr;
4402 asprintf(&freezer, "%s/%s", newpath, "cgroup.freeze");
4403 if (freezer) {
4404 FILE* fp = fopen(freezer, "r");
4405 if (fp != NULL) {
4406 int frozen;
4407 fscanf(fp, "%d", &frozen);
4408 if (frozen > 0) {
4409 dump_files("", newpath, skip_none, dump_from_fd);
4410 }
4411 fclose(fp);
4412 }
4413 free(freezer);
4414 }
4415 }
4416 }
4417 }
4418 closedir(dirp);
4419}
4420
4421void dump_frozen_cgroupfs() {
Li Li830179f2022-01-04 12:53:29 -08004422 MYLOGD("Adding frozen processes from %s\n", CGROUPFS_DIR);
4423 DurationReporter duration_reporter("FROZEN CGROUPFS");
4424 if (PropertiesHelper::IsDryRun()) return;
4425 dump_frozen_cgroupfs(CGROUPFS_DIR, 0, _add_file_from_fd);
4426}
4427
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004428void Dumpstate::UpdateProgress(int32_t delta_sec) {
4429 if (progress_ == nullptr) {
4430 MYLOGE("UpdateProgress: progress_ not set\n");
4431 return;
4432 }
Rhed Jaobf63d8a2020-07-21 15:42:55 +08004433 // This function updates progress related members of the dumpstate and reports
4434 // progress percentage to the bugreport client. Since it could be called by
4435 // different dump tasks at the same time if the parallel run is enabled, a
4436 // mutex lock is necessary here to synchronize the call.
4437 std::lock_guard<std::recursive_mutex> lock(mutex_);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004438
4439 // Always update progess so stats can be tuned...
Nandana Dutt402a8392019-06-14 14:25:13 +01004440 progress_->Inc(delta_sec);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004441
4442 // ...but only notifiy listeners when necessary.
4443 if (!options_->do_progress_updates) return;
4444
4445 int progress = progress_->Get();
4446 int max = progress_->GetMax();
Nandana Dutt402a8392019-06-14 14:25:13 +01004447 int percent = 100 * progress / max;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004448
Nandana Dutt402a8392019-06-14 14:25:13 +01004449 if (last_reported_percent_progress_ > 0 && percent <= last_reported_percent_progress_) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004450 return;
4451 }
Nandana Dutt402a8392019-06-14 14:25:13 +01004452 last_reported_percent_progress_ = percent;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004453
4454 if (control_socket_fd_ >= 0) {
4455 dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
4456 fsync(control_socket_fd_);
4457 }
4458
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004459 if (listener_ != nullptr) {
Nandana Dutt235c6672019-11-14 15:22:32 +00004460 if (percent % 10 == 0) {
4461 // We don't want to spam logcat, so only log multiples of 10.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004462 MYLOGD("Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004463 } else {
4464 // stderr is ignored on normal invocations, but useful when calling
4465 // /system/bin/dumpstate directly for debuggging.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004466 fprintf(stderr, "Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004467 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004468
4469 listener_->onProgress(percent);
4470 }
4471}
4472
4473void Dumpstate::TakeScreenshot(const std::string& path) {
4474 const std::string& real_path = path.empty() ? screenshot_path_ : path;
4475 int status =
4476 RunCommand("", {"/system/bin/screencap", "-p", real_path},
4477 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
4478 if (status == 0) {
4479 MYLOGD("Screenshot saved on %s\n", real_path.c_str());
4480 } else {
4481 MYLOGE("Failed to take screenshot on %s\n", real_path.c_str());
4482 }
Paul Chang0d2aad72020-02-13 20:04:03 +08004483 if (listener_ != nullptr) {
4484 // Show a visual indication to indicate screenshot is taken via
4485 // IDumpstateListener.onScreenshotTaken()
4486 listener_->onScreenshotTaken(status == 0);
4487 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004488}
4489
4490bool is_dir(const char* pathname) {
4491 struct stat info;
4492 if (stat(pathname, &info) == -1) {
4493 return false;
4494 }
4495 return S_ISDIR(info.st_mode);
4496}
4497
4498time_t get_mtime(int fd, time_t default_mtime) {
4499 struct stat info;
4500 if (fstat(fd, &info) == -1) {
4501 return default_mtime;
4502 }
4503 return info.st_mtime;
4504}