blob: 83b336c62f09d2b94e5d9281a6ff477a4d38ed53 [file] [log] [blame]
Colin Crossf45fa6b2012-03-26 12:38:26 -07001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Felipe Lemef0292972016-11-22 13:57:05 -080016
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070017#define LOG_TAG "dumpstate"
Kevin Jeon2c02e8e2022-07-07 21:45:17 +000018#define ATRACE_TAG ATRACE_TAG_ALWAYS
Colin Crossf45fa6b2012-03-26 12:38:26 -070019
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -070020#include <dirent.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070021#include <errno.h>
22#include <fcntl.h>
Nikita Ioffea325a572019-05-16 19:49:47 +010023#include <inttypes.h>
Felipe Lemead5f6c42015-11-30 14:26:46 -080024#include <libgen.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070025#include <limits.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010026#include <math.h>
27#include <poll.h>
Mark Salyzyn8f37aa52015-06-12 12:28:24 -070028#include <stdbool.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070029#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -070032#include <sys/mount.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080033#include <sys/poll.h>
Christopher Ferris7dc7f322014-07-22 16:08:19 -070034#include <sys/prctl.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070035#include <sys/resource.h>
36#include <sys/stat.h>
37#include <sys/time.h>
38#include <sys/wait.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010039#include <signal.h>
40#include <stdarg.h>
41#include <string.h>
42#include <sys/capability.h>
43#include <sys/inotify.h>
44#include <sys/klog.h>
45#include <time.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070046#include <unistd.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070047
48#include <chrono>
Hridya Valsarajuac582cd2019-08-05 15:39:54 -070049#include <cmath>
Abhijeet Kaurd3cca0d2019-03-25 12:04:16 +000050#include <fstream>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070051#include <functional>
52#include <future>
Narayan Kamath8f788292017-05-25 13:20:39 +010053#include <memory>
Hridya Valsarajuac582cd2019-08-05 15:39:54 -070054#include <numeric>
Narayan Kamath8f788292017-05-25 13:20:39 +010055#include <regex>
56#include <set>
57#include <string>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070058#include <utility>
Narayan Kamath8f788292017-05-25 13:20:39 +010059#include <vector>
Colin Crossf45fa6b2012-03-26 12:38:26 -070060
Kedar Chitnis9fd8c052021-11-16 09:09:22 +000061#include <aidl/android/hardware/dumpstate/IDumpstateDevice.h>
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +000062#include <android_app_admin_flags.h>
Felipe Leme96c2bbb2016-09-26 09:21:21 -070063#include <android-base/file.h>
64#include <android-base/properties.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070065#include <android-base/scopeguard.h>
Elliott Hughes9dc117c2015-12-07 14:21:50 -080066#include <android-base/stringprintf.h>
Naveen Kalla058e1e82016-10-19 21:38:44 -070067#include <android-base/strings.h>
Andreas Gampeaff68432016-07-18 18:01:27 -070068#include <android-base/unique_fd.h>
Kedar Chitnis9fd8c052021-11-16 09:09:22 +000069#include <android/binder_manager.h>
70#include <android/binder_process.h>
Nikita Ioffea325a572019-05-16 19:49:47 +010071#include <android/content/pm/IPackageManagerNative.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080072#include <android/hardware/dumpstate/1.0/IDumpstateDevice.h>
Hunter Knepshield8540faf2020-02-04 19:47:20 -080073#include <android/hardware/dumpstate/1.1/IDumpstateDevice.h>
74#include <android/hardware/dumpstate/1.1/types.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080075#include <android/hidl/manager/1.0/IServiceManager.h>
Nandana Duttd2f5f082019-01-18 17:13:52 +000076#include <android/os/IIncidentCompanion.h>
Nikita Ioffea325a572019-05-16 19:49:47 +010077#include <binder/IServiceManager.h>
Nikhil Kumar28ce35e2023-01-10 14:32:44 +000078#include <cutils/multiuser.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080079#include <cutils/native_handle.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070080#include <cutils/properties.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010081#include <cutils/sockets.h>
Kevin Jeon2c02e8e2022-07-07 21:45:17 +000082#include <cutils/trace.h>
Nandana Duttfaafd522019-03-11 09:23:09 +000083#include <debuggerd/client.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080084#include <dumpsys.h>
Nandana Duttfaafd522019-03-11 09:23:09 +000085#include <dumputils/dump_utils.h>
Sahana Raof35ed432019-07-12 10:47:52 +010086#include <hardware_legacy/power.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080087#include <hidl/ServiceManagement.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010088#include <log/log.h>
Tom Cherryf4472f32020-08-05 09:31:17 -070089#include <log/log_read.h>
Felipe Leme75876a22016-10-27 16:31:27 -070090#include <openssl/sha.h>
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070091#include <private/android_filesystem_config.h>
92#include <private/android_logger.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080093#include <serviceutils/PriorityDumper.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070094#include <utils/StrongPointer.h>
Devin Moore8df81bb2022-06-08 22:47:02 +000095#include <vintf/VintfObject.h>
Felipe Lemef0292972016-11-22 13:57:05 -080096#include "DumpstateInternal.h"
Felipe Leme75876a22016-10-27 16:31:27 -070097#include "DumpstateService.h"
Colin Crossf45fa6b2012-03-26 12:38:26 -070098#include "dumpstate.h"
Felipe Leme6e01fa62015-11-11 19:35:14 -080099
Kedar Chitnis9fd8c052021-11-16 09:09:22 +0000100namespace dumpstate_hal_hidl_1_0 = android::hardware::dumpstate::V1_0;
101namespace dumpstate_hal_hidl = android::hardware::dumpstate::V1_1;
102namespace dumpstate_hal_aidl = aidl::android::hardware::dumpstate;
103
Vishnu Naire97d6122018-01-18 13:58:56 -0800104using ::std::literals::chrono_literals::operator""ms;
105using ::std::literals::chrono_literals::operator""s;
Rhed Jao5377d792020-07-16 17:37:39 +0800106using ::std::placeholders::_1;
Steven Morelandcb7ef822016-11-29 13:20:37 -0800107
Felipe Leme47e9be22016-12-21 15:37:07 -0800108// TODO: remove once moved to namespace
Vishnu Naire97d6122018-01-18 13:58:56 -0800109using android::defaultServiceManager;
110using android::Dumpsys;
111using android::INVALID_OPERATION;
112using android::IServiceManager;
113using android::OK;
114using android::sp;
115using android::status_t;
116using android::String16;
117using android::String8;
118using android::TIMED_OUT;
119using android::UNKNOWN_ERROR;
120using android::Vector;
Nandana Dutt979388e2018-11-30 16:48:55 +0000121using android::base::StringPrintf;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000122using android::os::IDumpstateListener;
Felipe Leme47e9be22016-12-21 15:37:07 -0800123using android::os::dumpstate::CommandOptions;
124using android::os::dumpstate::DumpFileToFd;
Rhed Jao5377d792020-07-16 17:37:39 +0800125using android::os::dumpstate::DumpPool;
Vishnu Naire97d6122018-01-18 13:58:56 -0800126using android::os::dumpstate::PropertiesHelper;
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800127using android::os::dumpstate::TaskQueue;
Chris Morinbc223142022-02-04 14:17:11 -0800128using android::os::dumpstate::WaitForTask;
Felipe Leme47e9be22016-12-21 15:37:07 -0800129
Abhijeet Kaurcf234e82019-07-01 14:53:55 +0100130// Keep in sync with
131// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
132static const int TRACE_DUMP_TIMEOUT_MS = 10000; // 10 seconds
133
134/* Most simple commands have 10 as timeout, so 5 is a good estimate */
135static const int32_t WEIGHT_FILE = 5;
136
137// TODO: temporary variables and functions used during C++ refactoring
138static Dumpstate& ds = Dumpstate::GetInstance();
139static int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Nandana Dutt8d945c02019-08-14 13:30:07 +0100140 const CommandOptions& options = CommandOptions::DEFAULT,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800141 bool verbose_duration = false, int out_fd = STDOUT_FILENO) {
142 return ds.RunCommand(title, full_command, options, verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +0100143}
144
145// Reasonable value for max stats.
146static const int STATS_MAX_N_RUNS = 1000;
147static const long STATS_MAX_AVERAGE = 100000;
148
149CommandOptions Dumpstate::DEFAULT_DUMPSYS = CommandOptions::WithTimeout(30).Build();
150
Nandana Duttd2f5f082019-01-18 17:13:52 +0000151typedef Dumpstate::ConsentCallback::ConsentResult UserConsentResult;
152
Colin Crossf45fa6b2012-03-26 12:38:26 -0700153/* read before root is shed */
154static char cmdline_buf[16384] = "(unknown)";
Yi Kong19d5c002018-07-20 13:39:55 -0700155static const char *dump_traces_path = nullptr;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000156static const uint64_t USER_CONSENT_TIMEOUT_MS = 30 * 1000;
Hunter Knepshield70610fa2020-01-03 15:27:33 -0800157// Because telephony reports are significantly faster to collect (< 10 seconds vs. > 2 minutes),
158// it's often the case that they time out far too quickly for consent with such a hefty dialog for
159// the user to read. For telephony reports only, we increase the default timeout to 2 minutes to
160// roughly match full reports' durations.
161static const uint64_t TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS = 2 * 60 * 1000;
Colin Crossf45fa6b2012-03-26 12:38:26 -0700162
Felipe Leme1d486fe2016-10-14 18:06:47 -0700163// TODO: variables and functions below should be part of dumpstate object
164
Felipe Leme635ca312016-01-05 14:23:02 -0800165static std::set<std::string> mount_points;
166void add_mountinfo();
Felipe Leme78f2c862015-12-21 09:55:22 -0800167
Todd Poynor2a83daa2013-11-22 15:44:22 -0800168#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
Mark Salyzyn7d0a7622016-06-24 14:06:15 -0700169#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
Wei Wang509bb5d2017-06-09 14:42:12 -0700170#define BLK_DEV_SYS_DIR "/sys/block"
Todd Poynor2a83daa2013-11-22 15:44:22 -0800171
Felipe Lemee82a27d2016-01-05 13:35:44 -0800172#define RECOVERY_DIR "/cache/recovery"
Mark Salyzynd6ab0112016-03-25 12:56:39 -0700173#define RECOVERY_DATA_DIR "/data/misc/recovery"
Tianjie Xu75d53362018-04-11 16:42:28 -0700174#define UPDATE_ENGINE_LOG_DIR "/data/misc/update_engine_log"
Kelvin Zhang6eaa0f92022-09-12 09:29:19 -0700175#define UPDATE_ENGINE_PREF_DIR "/data/misc/update_engine/prefs"
Mark Salyzyn4d42dea2016-04-01 10:03:14 -0700176#define LOGPERSIST_DATA_DIR "/data/misc/logd"
Jerry Changa1df8a92020-01-02 16:03:39 +0800177#define PREREBOOT_DATA_DIR "/data/misc/prereboot"
David Brazdild2991962016-06-03 14:40:44 +0100178#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
179#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
Benedict Wong8f9d8a42019-01-03 16:19:38 -0800180#define XFRM_STAT_PROC_FILE "/proc/net/xfrm_stat"
Erik Kline08165202016-05-30 11:55:44 +0900181#define WLUTIL "/vendor/xbin/wlutil"
Vishnu Nair36b4cdb2017-11-17 10:27:05 -0800182#define WMTRACE_DATA_DIR "/data/misc/wmtrace"
Yifan Hong3945e1b2019-10-29 12:59:23 -0700183#define OTA_METADATA_DIR "/metadata/ota"
Yifan Hong0efa7972020-02-03 16:45:02 -0800184#define SNAPSHOTCTL_LOG_DIR "/data/misc/snapshotctl_log"
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +0900185#define LINKERCONFIG_DIR "/linkerconfig"
Calin Juravlef84d3692020-04-28 15:31:12 -0700186#define PACKAGE_DEX_USE_LIST "/data/system/package-dex-usage.list"
Primiano Tuccifaaaafb2021-01-14 12:26:29 +0000187#define SYSTEM_TRACE_SNAPSHOT "/data/misc/perfetto-traces/bugreport/systrace.pftrace"
Li Li2eedd412021-06-30 15:11:53 -0700188#define CGROUPFS_DIR "/sys/fs/cgroup"
Mårten Kongstad60195a72022-09-20 14:14:20 +0200189#define SDK_EXT_INFO "/apex/com.android.sdkext/bin/derive_sdk"
Jeff Sharkey9df29d52023-02-06 14:26:30 -0700190#define DROPBOX_DIR "/data/system/dropbox"
Mårten Kongstad5ad813f2023-09-28 10:09:18 +0200191#define PRINT_FLAGS "/system/bin/printflags"
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700192
Narayan Kamath8f788292017-05-25 13:20:39 +0100193// TODO(narayan): Since this information has to be kept in sync
194// with tombstoned, we should just put it in a common header.
195//
196// File: system/core/debuggerd/tombstoned/tombstoned.cpp
Narayan Kamathbd863722017-06-01 18:50:12 +0100197static const std::string TOMBSTONE_DIR = "/data/tombstones/";
198static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
199static const std::string ANR_DIR = "/data/anr/";
200static const std::string ANR_FILE_PREFIX = "anr_";
Woody Lin20767a92022-11-29 15:50:24 +0800201static const std::string SHUTDOWN_CHECKPOINTS_DIR = "/data/system/shutdown-checkpoints/";
202static const std::string SHUTDOWN_CHECKPOINTS_FILE_PREFIX = "checkpoints-";
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700203
Felipe Lemee844a9d2016-09-21 15:01:39 -0700204// TODO: temporary variables and functions used during C++ refactoring
Nandana Dutt979388e2018-11-30 16:48:55 +0000205
Nandana Dutt5c390032019-03-12 10:52:56 +0000206#define RETURN_IF_USER_DENIED_CONSENT() \
207 if (ds.IsUserConsentDenied()) { \
208 MYLOGE("Returning early as user denied consent to share bugreport with calling app."); \
209 return Dumpstate::RunStatus::USER_CONSENT_DENIED; \
210 }
211
212// Runs func_ptr, but checks user consent before and after running it. Returns USER_CONSENT_DENIED
213// if consent is found to be denied.
214#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(func_ptr, ...) \
215 RETURN_IF_USER_DENIED_CONSENT(); \
216 func_ptr(__VA_ARGS__); \
217 RETURN_IF_USER_DENIED_CONSENT();
218
Rhed Jao5377d792020-07-16 17:37:39 +0800219// Runs func_ptr, and logs a duration report after it's finished.
220#define RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, ...) \
221 { \
222 DurationReporter duration_reporter_in_macro(log_title); \
223 func_ptr(__VA_ARGS__); \
224 }
225
226// Similar with RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK, an additional duration report
227// is output after a slow function is finished.
228#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(log_title, func_ptr, ...) \
229 RETURN_IF_USER_DENIED_CONSENT(); \
230 RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, __VA_ARGS__); \
231 RETURN_IF_USER_DENIED_CONSENT();
232
Chris Morinbc223142022-02-04 14:17:11 -0800233#define WAIT_TASK_WITH_CONSENT_CHECK(future) \
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800234 RETURN_IF_USER_DENIED_CONSENT(); \
Chris Morinbc223142022-02-04 14:17:11 -0800235 WaitForTask(future); \
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800236 RETURN_IF_USER_DENIED_CONSENT();
237
Sahana Raof35ed432019-07-12 10:47:52 +0100238static const char* WAKE_LOCK_NAME = "dumpstate_wakelock";
239
Rhed Jao5377d792020-07-16 17:37:39 +0800240// Names of parallel tasks, they are used for the DumpPool to identify the dump
241// task and the log title of the duration report.
242static const std::string DUMP_TRACES_TASK = "DUMP TRACES";
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800243static const std::string DUMP_INCIDENT_REPORT_TASK = "INCIDENT REPORT";
Aaron Huang24d215d2022-04-27 18:51:16 +0800244static const std::string DUMP_NETSTATS_PROTO_TASK = "DUMP NETSTATS PROTO";
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800245static const std::string DUMP_HALS_TASK = "DUMP HALS";
246static const std::string DUMP_BOARD_TASK = "dumpstate_board()";
Rhed Jaoe017f982020-07-21 17:58:41 +0800247static const std::string DUMP_CHECKINS_TASK = "DUMP CHECKINS";
Kean Mariotti306633e2022-09-05 16:30:47 +0000248static const std::string POST_PROCESS_UI_TRACES_TASK = "POST-PROCESS UI TRACES";
Rhed Jao5377d792020-07-16 17:37:39 +0800249
Nandana Dutt979388e2018-11-30 16:48:55 +0000250namespace android {
251namespace os {
252namespace {
253
254static int Open(std::string path, int flags, mode_t mode = 0) {
255 int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
256 if (fd == -1) {
257 MYLOGE("open(%s, %s)\n", path.c_str(), strerror(errno));
258 }
259 return fd;
260}
261
mhasank2d75c442020-06-11 15:05:25 -0700262static int OpenForWrite(std::string path) {
263 return Open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
264 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
265}
Nandana Dutt979388e2018-11-30 16:48:55 +0000266
267static int OpenForRead(std::string path) {
268 return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
269}
270
271bool CopyFile(int in_fd, int out_fd) {
272 char buf[4096];
273 ssize_t byte_count;
274 while ((byte_count = TEMP_FAILURE_RETRY(read(in_fd, buf, sizeof(buf)))) > 0) {
275 if (!android::base::WriteFully(out_fd, buf, byte_count)) {
276 return false;
277 }
278 }
279 return (byte_count != -1);
280}
281
282static bool CopyFileToFd(const std::string& input_file, int out_fd) {
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000283 MYLOGD("Going to copy file (%s) to %d\n", input_file.c_str(), out_fd);
Nandana Dutt979388e2018-11-30 16:48:55 +0000284
285 // Obtain a handle to the source file.
286 android::base::unique_fd in_fd(OpenForRead(input_file));
287 if (out_fd != -1 && in_fd.get() != -1) {
288 if (CopyFile(in_fd.get(), out_fd)) {
289 return true;
290 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000291 MYLOGE("Failed to copy file: %s\n", strerror(errno));
Nandana Dutt979388e2018-11-30 16:48:55 +0000292 }
293 return false;
294}
295
Nandana Duttd2f5f082019-01-18 17:13:52 +0000296static bool UnlinkAndLogOnError(const std::string& file) {
Nandana Dutt8ae16e62020-03-27 10:20:22 +0000297 if (file.empty()) {
298 return false;
299 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000300 if (unlink(file.c_str())) {
301 MYLOGE("Failed to unlink file (%s): %s\n", file.c_str(), strerror(errno));
Nandana Duttd2f5f082019-01-18 17:13:52 +0000302 return false;
303 }
304 return true;
305}
Nandana Dutt979388e2018-11-30 16:48:55 +0000306
Nikita Ioffea325a572019-05-16 19:49:47 +0100307int64_t GetModuleMetadataVersion() {
308 auto binder = defaultServiceManager()->getService(android::String16("package_native"));
309 if (binder == nullptr) {
310 MYLOGE("Failed to retrieve package_native service");
311 return 0L;
312 }
313 auto package_service = android::interface_cast<content::pm::IPackageManagerNative>(binder);
314 std::string package_name;
315 auto status = package_service->getModuleMetadataPackageName(&package_name);
316 if (!status.isOk()) {
317 MYLOGE("Failed to retrieve module metadata package name: %s", status.toString8().c_str());
318 return 0L;
319 }
Nandana Duttdb379fa2019-10-09 16:54:41 +0100320 MYLOGD("Module metadata package name: %s\n", package_name.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100321 int64_t version_code;
322 status = package_service->getVersionCodeForPackage(android::String16(package_name.c_str()),
323 &version_code);
324 if (!status.isOk()) {
325 MYLOGE("Failed to retrieve module metadata version: %s", status.toString8().c_str());
326 return 0L;
327 }
328 return version_code;
329}
330
mhasank2d75c442020-06-11 15:05:25 -0700331static bool PathExists(const std::string& path) {
332 struct stat sb;
333 return stat(path.c_str(), &sb) == 0;
334}
335
336static bool CopyFileToFile(const std::string& input_file, const std::string& output_file) {
337 if (input_file == output_file) {
338 MYLOGD("Skipping copying bugreport file since the destination is the same (%s)\n",
339 output_file.c_str());
340 return false;
341 }
342 else if (PathExists(output_file)) {
343 MYLOGD("Cannot overwrite an existing file (%s)\n", output_file.c_str());
344 return false;
345 }
346
347 MYLOGD("Going to copy bugreport file (%s) to %s\n", input_file.c_str(), output_file.c_str());
348 android::base::unique_fd out_fd(OpenForWrite(output_file));
349 return CopyFileToFd(input_file, out_fd.get());
350}
351
Nandana Dutt979388e2018-11-30 16:48:55 +0000352} // namespace
353} // namespace os
354} // namespace android
355
Felipe Leme678727a2016-09-21 17:22:11 -0700356static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
Felipe Lemebda15a02016-11-16 17:48:25 -0800357 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
Rhed Jaoe017f982020-07-21 17:58:41 +0800358 long dumpsysTimeoutMs = 0, int out_fd = STDOUT_FILENO) {
359 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs, out_fd);
360}
361static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
362 int out_fd) {
363 return ds.RunDumpsys(title, dumpsysArgs, Dumpstate::DEFAULT_DUMPSYS, 0, out_fd);
Felipe Leme678727a2016-09-21 17:22:11 -0700364}
365static int DumpFile(const std::string& title, const std::string& path) {
366 return ds.DumpFile(title, path);
367}
Felipe Lemee82a27d2016-01-05 13:35:44 -0800368
Felipe Lemee844a9d2016-09-21 15:01:39 -0700369// Relative directory (inside the zip) for all files copied as-is into the bugreport.
370static const std::string ZIP_ROOT_DIR = "FS";
371
Vishnu Naire97d6122018-01-18 13:58:56 -0800372static const std::string kProtoPath = "proto/";
373static const std::string kProtoExt = ".proto";
Jie Song9fbfad02017-06-20 16:29:42 -0700374static const std::string kDumpstateBoardFiles[] = {
375 "dumpstate_board.txt",
Felipe Leme95d6ca52017-08-01 16:35:56 -0700376 "dumpstate_board.bin"
Jie Song9fbfad02017-06-20 16:29:42 -0700377};
378static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
379
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700380static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Lemed071c682016-10-20 16:48:00 -0700381static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700382
Felipe Lemef0292972016-11-22 13:57:05 -0800383static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
384
Narayan Kamath8f788292017-05-25 13:20:39 +0100385/*
Narayan Kamathbd863722017-06-01 18:50:12 +0100386 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
Rhed Jao01dc0c62020-06-03 17:13:30 +0800387 * The returned vector is sorted by the mtimes of the dumps with descending
Chris Morinc2cba7a2022-02-01 17:06:50 -0800388 * order.
Narayan Kamath8f788292017-05-25 13:20:39 +0100389 */
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700390static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
Chris Morinc2cba7a2022-02-01 17:06:50 -0800391 const std::string& file_prefix) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100392 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100393
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700394 if (dump_dir == nullptr) {
395 MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno));
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700396 return std::vector<DumpData>();
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700397 }
398
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700399 std::vector<DumpData> dump_data;
Narayan Kamathbd863722017-06-01 18:50:12 +0100400 struct dirent* entry = nullptr;
401 while ((entry = readdir(dump_dir.get()))) {
402 if (entry->d_type != DT_REG) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100403 continue;
404 }
405
Narayan Kamathbd863722017-06-01 18:50:12 +0100406 const std::string base_name(entry->d_name);
407 if (base_name.find(file_prefix) != 0) {
408 continue;
409 }
410
411 const std::string abs_path = dir_path + base_name;
412 android::base::unique_fd fd(
413 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
414 if (fd == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700415 MYLOGW("Unable to open dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamathbd863722017-06-01 18:50:12 +0100416 break;
417 }
418
419 struct stat st = {};
420 if (fstat(fd, &st) == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700421 MYLOGW("Unable to stat dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamath8f788292017-05-25 13:20:39 +0100422 continue;
423 }
424
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700425 dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700426 }
Rhed Jao01dc0c62020-06-03 17:13:30 +0800427 if (!dump_data.empty()) {
428 std::sort(dump_data.begin(), dump_data.end(),
429 [](const auto& a, const auto& b) { return a.mtime > b.mtime; });
430 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100431
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700432 return dump_data;
Narayan Kamath8f788292017-05-25 13:20:39 +0100433}
434
Narayan Kamathbd863722017-06-01 18:50:12 +0100435static bool AddDumps(const std::vector<DumpData>::const_iterator start,
436 const std::vector<DumpData>::const_iterator end,
437 const char* type_name, const bool add_to_zip) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100438 bool dumped = false;
Narayan Kamathbd863722017-06-01 18:50:12 +0100439 for (auto it = start; it != end; ++it) {
440 const std::string& name = it->name;
441 const int fd = it->fd;
Narayan Kamath8f788292017-05-25 13:20:39 +0100442 dumped = true;
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100443
444 // Seek to the beginning of the file before dumping any data. A given
445 // DumpData entry might be dumped multiple times in the report.
446 //
447 // For example, the most recent ANR entry is dumped to the body of the
448 // main entry and it also shows up as a separate entry in the bugreport
449 // ZIP file.
450 if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) {
451 MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(),
452 strerror(errno));
453 }
454
Chris Morinc2cba7a2022-02-01 17:06:50 -0800455 if (add_to_zip) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800456 if (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd, /* timeout = */ 0ms) != OK) {
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100457 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100458 }
459 } else {
460 dump_file_from_fd(type_name, name.c_str(), fd);
461 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100462 }
463
464 return dumped;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700465}
466
Felipe Leme635ca312016-01-05 14:23:02 -0800467// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700468void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800469 char path[PATH_MAX];
470
471 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
472 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700473 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800474 char linkname[PATH_MAX];
475 ssize_t r = readlink(path, linkname, PATH_MAX);
476 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800477 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800478 return;
479 }
480 linkname[r] = '\0';
481
482 if (mount_points.find(linkname) == mount_points.end()) {
483 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700484 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700485 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
Felipe Leme635ca312016-01-05 14:23:02 -0800486 mount_points.insert(linkname);
487 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800488 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800489 }
490 }
491}
492
493void add_mountinfo() {
Felipe Leme678727a2016-09-21 17:22:11 -0700494 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800495 mount_points.clear();
Felipe Leme46b85da2016-11-21 17:40:45 -0800496 DurationReporter duration_reporter(title, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700497 for_each_pid(do_mountinfo, nullptr);
498 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800499}
500
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700501static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
502{
503 DIR *d;
504 struct dirent *de;
505 char path[PATH_MAX];
506
507 d = opendir(driverpath);
Yi Kong19d5c002018-07-20 13:39:55 -0700508 if (d == nullptr) {
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700509 return;
510 }
511
512 while ((de = readdir(d))) {
513 if (de->d_type != DT_LNK) {
514 continue;
515 }
516 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700517 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700518 }
519
520 closedir(d);
521}
522
Mark Salyzyn326842f2015-04-30 09:49:41 -0700523static bool skip_not_stat(const char *path) {
524 static const char stat[] = "/stat";
525 size_t len = strlen(path);
526 if (path[len - 1] == '/') { /* Directory? */
527 return false;
528 }
529 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
530}
531
Jeff Sharkey9df29d52023-02-06 14:26:30 -0700532static bool skip_wtf_strictmode(const char *path) {
533 if (strstr(path, "_wtf")) {
534 return true;
535 } else if (strstr(path, "_strictmode")) {
536 return true;
537 }
538 return false;
539}
540
Felipe Leme4c2d6632016-09-28 14:32:00 -0700541static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800542 return false;
543}
544
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700545unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700546
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800547//
548// stat offsets
549// Name units description
550// ---- ----- -----------
551// read I/Os requests number of read I/Os processed
552#define __STAT_READ_IOS 0
553// read merges requests number of read I/Os merged with in-queue I/O
554#define __STAT_READ_MERGES 1
555// read sectors sectors number of sectors read
556#define __STAT_READ_SECTORS 2
557// read ticks milliseconds total wait time for read requests
558#define __STAT_READ_TICKS 3
559// write I/Os requests number of write I/Os processed
560#define __STAT_WRITE_IOS 4
561// write merges requests number of write I/Os merged with in-queue I/O
562#define __STAT_WRITE_MERGES 5
563// write sectors sectors number of sectors written
564#define __STAT_WRITE_SECTORS 6
565// write ticks milliseconds total wait time for write requests
566#define __STAT_WRITE_TICKS 7
567// in_flight requests number of I/Os currently in flight
568#define __STAT_IN_FLIGHT 8
569// io_ticks milliseconds total time this block device has been active
570#define __STAT_IO_TICKS 9
571// time_in_queue milliseconds total wait time for all requests
572#define __STAT_IN_QUEUE 10
573#define __STAT_NUMBER_FIELD 11
574//
575// read I/Os, write I/Os
576// =====================
577//
578// These values increment when an I/O request completes.
579//
580// read merges, write merges
581// =========================
582//
583// These values increment when an I/O request is merged with an
584// already-queued I/O request.
585//
586// read sectors, write sectors
587// ===========================
588//
589// These values count the number of sectors read from or written to this
590// block device. The "sectors" in question are the standard UNIX 512-byte
591// sectors, not any device- or filesystem-specific block size. The
592// counters are incremented when the I/O completes.
593#define SECTOR_SIZE 512
594//
595// read ticks, write ticks
596// =======================
597//
598// These values count the number of milliseconds that I/O requests have
599// waited on this block device. If there are multiple I/O requests waiting,
600// these values will increase at a rate greater than 1000/second; for
601// example, if 60 read requests wait for an average of 30 ms, the read_ticks
602// field will increase by 60*30 = 1800.
603//
604// in_flight
605// =========
606//
607// This value counts the number of I/O requests that have been issued to
608// the device driver but have not yet completed. It does not include I/O
609// requests that are in the queue but not yet issued to the device driver.
610//
611// io_ticks
612// ========
613//
614// This value counts the number of milliseconds during which the device has
615// had I/O requests queued.
616//
617// time_in_queue
618// =============
619//
620// This value counts the number of milliseconds that I/O requests have waited
621// on this block device. If there are multiple I/O requests waiting, this
622// value will increase as the product of the number of milliseconds times the
623// number of requests waiting (see "read ticks" above for an example).
624#define S_TO_MS 1000
625//
626
Mark Salyzyn326842f2015-04-30 09:49:41 -0700627static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800628 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700629 bool z;
Yi Kong19d5c002018-07-20 13:39:55 -0700630 char *cp, *buffer = nullptr;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700631 size_t i = 0;
Josh Gao7c4258c2018-06-25 13:40:08 -0700632 FILE *fp = fdopen(dup(fd), "rb");
Mark Salyzyn326842f2015-04-30 09:49:41 -0700633 getline(&buffer, &i, fp);
634 fclose(fp);
635 if (!buffer) {
636 return -errno;
637 }
638 i = strlen(buffer);
639 while ((i > 0) && (buffer[i - 1] == '\n')) {
640 buffer[--i] = '\0';
641 }
642 if (!*buffer) {
643 free(buffer);
644 return 0;
645 }
646 z = true;
647 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800648 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700649 if (fields[i] != 0) {
650 z = false;
651 }
652 }
653 if (z) { /* never accessed */
654 free(buffer);
655 return 0;
656 }
657
Wei Wang509bb5d2017-06-09 14:42:12 -0700658 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
659 path += sizeof(BLK_DEV_SYS_DIR) - 1;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700660 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700661
662 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
663 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
664 "W-wait", "in-fli", "activ", "T-wait", path, buffer);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700665 free(buffer);
666
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800667 if (fields[__STAT_IO_TICKS]) {
668 unsigned long read_perf = 0;
669 unsigned long read_ios = 0;
670 if (fields[__STAT_READ_TICKS]) {
671 unsigned long long divisor = fields[__STAT_READ_TICKS]
672 * fields[__STAT_IO_TICKS];
673 read_perf = ((unsigned long long)SECTOR_SIZE
674 * fields[__STAT_READ_SECTORS]
675 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
676 / divisor;
677 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
678 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
679 / divisor;
680 }
681
682 unsigned long write_perf = 0;
683 unsigned long write_ios = 0;
684 if (fields[__STAT_WRITE_TICKS]) {
685 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
686 * fields[__STAT_IO_TICKS];
687 write_perf = ((unsigned long long)SECTOR_SIZE
688 * fields[__STAT_WRITE_SECTORS]
689 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
690 / divisor;
691 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
692 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
693 / divisor;
694 }
695
696 unsigned queue = (fields[__STAT_IN_QUEUE]
697 + (fields[__STAT_IO_TICKS] >> 1))
698 / fields[__STAT_IO_TICKS];
699
700 if (!write_perf && !write_ios) {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700701 printf("%-30s: perf(ios) rd: %luKB/s(%lu/s) q: %u\n", path, read_perf, read_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800702 } else {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700703 printf("%-30s: perf(ios) rd: %luKB/s(%lu/s) wr: %luKB/s(%lu/s) q: %u\n", path, read_perf,
Felipe Lemed8b94e52016-12-08 10:21:44 -0800704 read_ios, write_perf, write_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800705 }
706
707 /* bugreport timeout factor adjustment */
708 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
709 worst_write_perf = write_perf;
710 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700711 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700712 return 0;
713}
714
Yao Chenbe3bbc12018-01-17 16:31:10 -0800715static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
716
Tom Cherryf4472f32020-08-05 09:31:17 -0700717// Returns the actual readable size of the given buffer or -1 on error.
718static long logcat_buffer_readable_size(const std::string& buffer) {
719 std::unique_ptr<logger_list, decltype(&android_logger_list_free)> logger_list{
720 android_logger_list_alloc(0, 0, 0), &android_logger_list_free};
721 auto logger = android_logger_open(logger_list.get(), android_name_to_log_id(buffer.c_str()));
722
723 return android_logger_get_log_readable_size(logger);
724}
725
726// Returns timeout in ms to read a list of buffers.
Yao Chenbe3bbc12018-01-17 16:31:10 -0800727static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
728 unsigned long timeout_ms = 0;
729 for (const auto& buffer : buffers) {
Tom Cherryf4472f32020-08-05 09:31:17 -0700730 long readable_size = logcat_buffer_readable_size(buffer);
731 if (readable_size > 0) {
732 // Engineering margin is ten-fold our guess.
733 timeout_ms += 10 * (readable_size + worst_write_perf) / worst_write_perf;
734 }
Yao Chenbe3bbc12018-01-17 16:31:10 -0800735 }
736 return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700737}
738
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800739// Opens a socket and returns its file descriptor.
740static int open_socket(const char* service);
741
Nandana Duttd2f5f082019-01-18 17:13:52 +0000742Dumpstate::ConsentCallback::ConsentCallback() : result_(UNAVAILABLE), start_time_(Nanotime()) {
743}
744
745android::binder::Status Dumpstate::ConsentCallback::onReportApproved() {
746 std::lock_guard<std::mutex> lock(lock_);
747 result_ = APPROVED;
748 MYLOGD("User approved consent to share bugreport\n");
Paul Chang0d2aad72020-02-13 20:04:03 +0800749
750 // Maybe copy screenshot so calling app can display the screenshot to the user as soon as
751 // consent is granted.
752 if (ds.options_->is_screenshot_copied) {
753 return android::binder::Status::ok();
754 }
755
756 if (!ds.options_->do_screenshot || ds.options_->screenshot_fd.get() == -1 ||
757 !ds.do_early_screenshot_) {
758 return android::binder::Status::ok();
759 }
760
761 bool copy_succeeded = android::os::CopyFileToFd(ds.screenshot_path_,
762 ds.options_->screenshot_fd.get());
763 ds.options_->is_screenshot_copied = copy_succeeded;
764 if (copy_succeeded) {
765 android::os::UnlinkAndLogOnError(ds.screenshot_path_);
766 }
Nandana Duttd2f5f082019-01-18 17:13:52 +0000767 return android::binder::Status::ok();
768}
769
770android::binder::Status Dumpstate::ConsentCallback::onReportDenied() {
771 std::lock_guard<std::mutex> lock(lock_);
772 result_ = DENIED;
773 MYLOGW("User denied consent to share bugreport\n");
774 return android::binder::Status::ok();
775}
776
777UserConsentResult Dumpstate::ConsentCallback::getResult() {
778 std::lock_guard<std::mutex> lock(lock_);
779 return result_;
780}
781
782uint64_t Dumpstate::ConsentCallback::getElapsedTimeMs() const {
Hunter Knepshieldf0a39052020-01-03 14:53:04 -0800783 return (Nanotime() - start_time_) / NANOS_PER_MILLI;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000784}
785
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700786void Dumpstate::PrintHeader() const {
Mårten Kongstad60195a72022-09-20 14:14:20 +0200787 std::string build, fingerprint, radio, bootloader, network, sdkversion;
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700788 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700789
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700790 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
791 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700792 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
793 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
794 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
Mårten Kongstad60195a72022-09-20 14:14:20 +0200795 sdkversion = android::base::GetProperty("ro.build.version.sdk", "(unknown)");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700796 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
Colin Crossf45fa6b2012-03-26 12:38:26 -0700797
Felipe Lemed8b94e52016-12-08 10:21:44 -0800798 printf("========================================================\n");
799 printf("== dumpstate: %s\n", date);
800 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700801
Felipe Lemed8b94e52016-12-08 10:21:44 -0800802 printf("\n");
803 printf("Build: %s\n", build.c_str());
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700804 // NOTE: fingerprint entry format is important for other tools.
Felipe Lemed8b94e52016-12-08 10:21:44 -0800805 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
806 printf("Bootloader: %s\n", bootloader.c_str());
807 printf("Radio: %s\n", radio.c_str());
808 printf("Network: %s\n", network.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100809 int64_t module_metadata_version = android::os::GetModuleMetadataVersion();
810 if (module_metadata_version != 0) {
811 printf("Module Metadata version: %" PRId64 "\n", module_metadata_version);
812 }
Mårten Kongstad60195a72022-09-20 14:14:20 +0200813 printf("Android SDK version: %s\n", sdkversion.c_str());
814 printf("SDK extensions: ");
815 RunCommandToFd(STDOUT_FILENO, "", {SDK_EXT_INFO, "--header"},
816 CommandOptions::WithTimeout(1).Always().DropRoot().Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700817
Felipe Lemed8b94e52016-12-08 10:21:44 -0800818 printf("Kernel: ");
Felipe Lemef0292972016-11-22 13:57:05 -0800819 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
Felipe Lemed8b94e52016-12-08 10:21:44 -0800820 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
Devin Moore09fde8d2023-03-21 16:28:22 +0000821 printf("Bootconfig: ");
822 DumpFileToFd(STDOUT_FILENO, "", "/proc/bootconfig");
Felipe Leme7709f8a2017-12-05 09:30:09 -0800823 printf("Uptime: ");
824 RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"},
825 CommandOptions::WithTimeout(1).Always().Build());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800826 printf("Bugreport format version: %s\n", version_.c_str());
Kevin Jeonfa64e642023-07-27 11:36:41 -0400827 printf(
828 "Dumpstate info: id=%d pid=%d dry_run=%d parallel_run=%d strict_run=%d args=%s "
829 "bugreport_mode=%s\n",
830 id_, pid_, PropertiesHelper::IsDryRun(), PropertiesHelper::IsParallelRun(),
831 PropertiesHelper::IsStrictRun(), options_->args.c_str(),
832 options_->bugreport_mode_string.c_str());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800833 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800834}
835
Felipe Leme24b66ee2016-06-16 10:55:26 -0700836// List of file extensions that can cause a zip file attachment to be rejected by some email
837// service providers.
838static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
839 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
840 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
841 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
842};
843
Vishnu Naire97d6122018-01-18 13:58:56 -0800844status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd,
845 std::chrono::milliseconds timeout = 0ms) {
Felipe Leme24b66ee2016-06-16 10:55:26 -0700846 std::string valid_name = entry_name;
847
848 // Rename extension if necessary.
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -0700849 size_t idx = entry_name.rfind('.');
Felipe Leme24b66ee2016-06-16 10:55:26 -0700850 if (idx != std::string::npos) {
851 std::string extension = entry_name.substr(idx);
852 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
853 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
854 valid_name = entry_name + ".renamed";
855 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
856 }
857 }
858
Felipe Leme6fe9db62016-02-12 09:04:16 -0800859 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
860 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Kevin Jeon9bbe0ac2022-05-05 22:05:43 +0000861 size_t flags = ZipWriter::kCompress | ZipWriter::kDefaultCompression;
862 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), flags,
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700863 get_mtime(fd, ds.now_));
Felipe Leme1d486fe2016-10-14 18:06:47 -0700864 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700865 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700866 ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800867 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800868 }
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000869 bool finished_entry = false;
870 auto finish_entry = [this, &finished_entry] {
871 if (!finished_entry) {
872 // This should only be called when we're going to return an earlier error,
873 // which would've been logged. This may imply the file is already corrupt
874 // and any further logging from FinishEntry is more likely to mislead than
875 // not.
876 this->zip_writer_->FinishEntry();
877 }
878 };
879 auto scope_guard = android::base::make_scope_guard(finish_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -0800880 auto start = std::chrono::steady_clock::now();
881 auto end = start + timeout;
882 struct pollfd pfd = {fd, POLLIN};
Felipe Lemee82a27d2016-01-05 13:35:44 -0800883
Felipe Leme770410d2016-01-26 17:07:14 -0800884 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800885 while (1) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800886 if (timeout.count() > 0) {
887 // lambda to recalculate the timeout.
888 auto time_left_ms = [end]() {
889 auto now = std::chrono::steady_clock::now();
890 auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
891 return std::max(diff.count(), 0LL);
892 };
893
894 int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
895 if (rc < 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000896 MYLOGE("Error in poll while adding from fd to zip entry %s:%s\n",
897 entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800898 return -errno;
899 } else if (rc == 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000900 MYLOGE("Timed out adding from fd to zip entry %s:%s Timeout:%lldms\n",
Vishnu Naire97d6122018-01-18 13:58:56 -0800901 entry_name.c_str(), strerror(errno), timeout.count());
902 return TIMED_OUT;
903 }
904 }
905
Zach Riggle22200402016-08-18 01:01:24 -0400906 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800907 if (bytes_read == 0) {
908 break;
909 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800910 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800911 return -errno;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800912 }
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700913 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800914 if (err) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700915 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800916 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800917 }
918 }
919
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700920 err = zip_writer_->FinishEntry();
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000921 finished_entry = true;
Felipe Leme1d486fe2016-10-14 18:06:47 -0700922 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700923 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800924 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800925 }
926
Vishnu Naire97d6122018-01-18 13:58:56 -0800927 return OK;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800928}
929
Felipe Leme1d486fe2016-10-14 18:06:47 -0700930bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
931 android::base::unique_fd fd(
932 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700933 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800934 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800935 return false;
936 }
937
Vishnu Naire97d6122018-01-18 13:58:56 -0800938 return (AddZipEntryFromFd(entry_name, fd.get()) == OK);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800939}
940
941/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700942static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800943 return (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) == OK) ? 0 : 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800944}
945
Felipe Leme1d486fe2016-10-14 18:06:47 -0700946void Dumpstate::AddDir(const std::string& dir, bool recursive) {
Felipe Leme678727a2016-09-21 17:22:11 -0700947 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
Felipe Leme46b85da2016-11-21 17:40:45 -0800948 DurationReporter duration_reporter(dir, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700949 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800950}
951
Felipe Leme1d486fe2016-10-14 18:06:47 -0700952bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800953 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Kevin Jeon9bbe0ac2022-05-05 22:05:43 +0000954 size_t flags = ZipWriter::kCompress | ZipWriter::kDefaultCompression;
955 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), flags, ds.now_);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700956 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700957 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700958 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800959 return false;
960 }
961
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700962 err = zip_writer_->WriteBytes(content.c_str(), content.length());
Felipe Leme1d486fe2016-10-14 18:06:47 -0700963 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700964 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700965 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800966 return false;
967 }
968
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700969 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700970 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700971 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800972 return false;
973 }
974
975 return true;
976}
977
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800978static void DoKmsg() {
979 struct stat st;
980 if (!stat(PSTORE_LAST_KMSG, &st)) {
981 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
982 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
983 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
984 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
985 } else {
986 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
987 DumpFile("LAST KMSG", "/proc/last_kmsg");
988 }
989}
990
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800991static void DoKernelLogcat() {
Yao Chenbe3bbc12018-01-17 16:31:10 -0800992 unsigned long timeout_ms = logcat_timeout({"kernel"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800993 RunCommand(
994 "KERNEL LOG",
995 {"logcat", "-b", "kernel", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
996 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
997}
998
Nandana Duttdb379fa2019-10-09 16:54:41 +0100999static void DoSystemLogcat(time_t since) {
1000 char since_str[80];
1001 strftime(since_str, sizeof(since_str), "%Y-%m-%d %H:%M:%S.000", localtime(&since));
1002
1003 unsigned long timeout_ms = logcat_timeout({"main", "system", "crash"});
1004 RunCommand("SYSTEM LOG",
1005 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v", "-T",
1006 since_str},
1007 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1008}
1009
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001010static void DoRadioLogcat() {
1011 unsigned long timeout_ms = logcat_timeout({"radio"});
1012 RunCommand(
1013 "RADIO LOG",
1014 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1015 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
1016}
1017
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001018static void DoLogcat() {
Vishnu Nair6921f802017-11-22 09:17:23 -08001019 unsigned long timeout_ms;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001020 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
1021 // calculate timeout
Yao Chenbe3bbc12018-01-17 16:31:10 -08001022 timeout_ms = logcat_timeout({"main", "system", "crash"});
Tony Makae737652017-03-30 17:47:09 +01001023 RunCommand("SYSTEM LOG",
Vishnu Nair6921f802017-11-22 09:17:23 -08001024 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1025 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -08001026 timeout_ms = logcat_timeout({"events"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001027 RunCommand(
1028 "EVENT LOG",
1029 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001030 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Yao Chenbe3bbc12018-01-17 16:31:10 -08001031 timeout_ms = logcat_timeout({"stats"});
1032 RunCommand(
1033 "STATS LOG",
1034 {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001035 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001036 DoRadioLogcat();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001037
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001038 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001039 RunCommand("LAST LOGCAT", {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable",
1040 "-v", "uid", "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001041}
1042
Mike Ma5c267872019-08-21 11:31:34 -07001043static void DumpIncidentReport() {
Mike Ma5c267872019-08-21 11:31:34 -07001044 const std::string path = ds.bugreport_internal_dir_ + "/tmp_incident_report";
1045 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1046 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1047 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1048 if (fd < 0) {
1049 MYLOGE("Could not open %s to dump incident report.\n", path.c_str());
1050 return;
1051 }
Kevin Jeonfa64e642023-07-27 11:36:41 -04001052 RunCommandToFd(fd, "", {"incident", "-u"},
1053 CommandOptions::WithTimeout(PropertiesHelper::IsStrictRun() ? 20 : 120).Build());
Mike Ma5c267872019-08-21 11:31:34 -07001054 bool empty = 0 == lseek(fd, 0, SEEK_END);
1055 if (!empty) {
1056 // Use a different name from "incident.proto"
1057 // /proto/incident.proto is reserved for incident service dump
1058 // i.e. metadata for debugging.
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001059 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "incident_report" + kProtoExt,
1060 path);
1061 } else {
1062 unlink(path.c_str());
Mike Ma5c267872019-08-21 11:31:34 -07001063 }
Mike Ma5c267872019-08-21 11:31:34 -07001064}
1065
Aaron Huang24d215d2022-04-27 18:51:16 +08001066static void DumpNetstatsProto() {
1067 const std::string path = ds.bugreport_internal_dir_ + "/tmp_netstats_proto";
1068 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1069 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1070 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1071 if (fd < 0) {
1072 MYLOGE("Could not open %s to dump netstats proto.\n", path.c_str());
1073 return;
1074 }
1075 RunCommandToFd(fd, "", {"dumpsys", "netstats", "--proto"},
Kevin Jeon2fb3dd62022-09-28 18:48:55 +00001076 CommandOptions::WithTimeout(5).Build());
Aaron Huang24d215d2022-04-27 18:51:16 +08001077 bool empty = 0 == lseek(fd, 0, SEEK_END);
1078 if (!empty) {
1079 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "netstats" + kProtoExt,
1080 path);
1081 } else {
1082 unlink(path.c_str());
1083 }
1084}
1085
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001086static void MaybeAddSystemTraceToZip() {
1087 // This function copies into the .zip the system trace that was snapshotted
1088 // by the early call to MaybeSnapshotSystemTrace(), if any background
1089 // tracing was happening.
Kean Mariotti853b73a2023-07-27 12:40:30 +00001090 bool system_trace_exists = access(SYSTEM_TRACE_SNAPSHOT, F_OK) == 0;
1091 if (!system_trace_exists) {
1092 // No background trace was happening at the time MaybeSnapshotSystemTrace() was invoked.
1093 if (!PropertiesHelper::IsUserBuild()) {
1094 MYLOGI(
1095 "No system traces found. Check for previously uploaded traces by looking for "
1096 "go/trace-uuid in logcat")
1097 }
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001098 return;
1099 }
1100 ds.AddZipEntry(
1101 ZIP_ROOT_DIR + SYSTEM_TRACE_SNAPSHOT,
1102 SYSTEM_TRACE_SNAPSHOT);
1103 android::os::UnlinkAndLogOnError(SYSTEM_TRACE_SNAPSHOT);
1104}
1105
Sunny Goyal35949782019-11-19 15:54:36 -08001106static void DumpVisibleWindowViews() {
Sunny Goyal35949782019-11-19 15:54:36 -08001107 DurationReporter duration_reporter("VISIBLE WINDOW VIEWS");
1108 const std::string path = ds.bugreport_internal_dir_ + "/tmp_visible_window_views";
1109 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1110 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1111 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1112 if (fd < 0) {
1113 MYLOGE("Could not open %s to dump visible views.\n", path.c_str());
1114 return;
1115 }
1116 RunCommandToFd(fd, "", {"cmd", "window", "dump-visible-window-views"},
Kevin Jeon774abde2022-09-28 18:20:43 +00001117 CommandOptions::WithTimeout(10).Build());
Sunny Goyal35949782019-11-19 15:54:36 -08001118 bool empty = 0 == lseek(fd, 0, SEEK_END);
1119 if (!empty) {
1120 ds.AddZipEntry("visible_windows.zip", path);
1121 } else {
1122 MYLOGW("Failed to dump visible windows\n");
1123 }
1124 unlink(path.c_str());
1125}
1126
Jayachandran Ca94c7172017-06-10 15:08:12 -07001127static void DumpIpTablesAsRoot() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001128 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
1129 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +09001130 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001131 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +09001132 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
1133 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
1134 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
1135 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001136}
1137
Woody Lin20767a92022-11-29 15:50:24 +08001138static void DumpShutdownCheckpoints() {
1139 const bool shutdown_checkpoints_dumped = AddDumps(
1140 ds.shutdown_checkpoints_.begin(), ds.shutdown_checkpoints_.end(),
1141 "SHUTDOWN CHECKPOINTS", false /* add_to_zip */);
1142 if (!shutdown_checkpoints_dumped) {
1143 printf("*** NO SHUTDOWN CHECKPOINTS to dump in %s\n\n",
1144 SHUTDOWN_CHECKPOINTS_DIR.c_str());
1145 }
1146}
1147
David Andersond9ba4752018-12-11 18:26:59 -08001148static void DumpDynamicPartitionInfo() {
1149 if (!::android::base::GetBoolProperty("ro.boot.dynamic_partitions", false)) {
1150 return;
1151 }
1152
1153 RunCommand("LPDUMP", {"lpdump", "--all"});
David Anderson6650ade2019-10-02 15:18:59 -07001154 RunCommand("DEVICE-MAPPER", {"gsid", "dump-device-mapper"});
David Andersond9ba4752018-12-11 18:26:59 -08001155}
1156
Chris Morin5a50d482022-02-01 17:41:18 -08001157static void AddAnrTraceDir(const std::string& anr_traces_dir) {
Narayan Kamath8f788292017-05-25 13:20:39 +01001158 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
1159 anr_traces_dir.c_str());
1160
1161 // If we're here, dump_traces_path will always be a temporary file
1162 // (created with mkostemp or similar) that contains dumps taken earlier
1163 // on in the process.
1164 if (dump_traces_path != nullptr) {
Chris Morin5a50d482022-02-01 17:41:18 -08001165 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
1166 dump_traces_path);
1167 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
Narayan Kamath8f788292017-05-25 13:20:39 +01001168
1169 const int ret = unlink(dump_traces_path);
1170 if (ret == -1) {
1171 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
1172 strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -07001173 }
1174 }
1175
Narayan Kamathbd863722017-06-01 18:50:12 +01001176 // Add a specific message for the first ANR Dump.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001177 if (ds.anr_data_.size() > 0) {
Chris Morin5a50d482022-02-01 17:41:18 -08001178 // The "last" ANR will always be present in the body of the main entry.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001179 AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1,
Chris Morin5a50d482022-02-01 17:41:18 -08001180 "VM TRACES AT LAST ANR", false /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001181
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001182 // Historical ANRs are always included as separate entries in the bugreport zip file.
Chris Morin5a50d482022-02-01 17:41:18 -08001183 AddDumps(ds.anr_data_.begin(), ds.anr_data_.end(),
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001184 "HISTORICAL ANR", true /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001185 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +01001186 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
1187 }
1188}
1189
1190static void AddAnrTraceFiles() {
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001191 std::string anr_traces_dir = "/data/anr";
Narayan Kamath8f788292017-05-25 13:20:39 +01001192
Chris Morin5a50d482022-02-01 17:41:18 -08001193 AddAnrTraceDir(anr_traces_dir);
Narayan Kamath8f788292017-05-25 13:20:39 +01001194
Makoto Onuki83ec63f2019-01-31 17:08:59 -08001195 RunCommand("ANR FILES", {"ls", "-lt", ANR_DIR});
1196
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001197 // Slow traces for slow operations.
Felipe Lemee184f662016-10-27 10:04:47 -07001198 struct stat st;
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001199 int i = 0;
1200 while (true) {
1201 const std::string slow_trace_path =
1202 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
1203 if (stat(slow_trace_path.c_str(), &st)) {
1204 // No traces file at this index, done with the files.
1205 break;
Felipe Lemee184f662016-10-27 10:04:47 -07001206 }
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001207 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
1208 i++;
Felipe Lemee184f662016-10-27 10:04:47 -07001209 }
1210}
1211
Wei Wang509bb5d2017-06-09 14:42:12 -07001212static void DumpBlockStatFiles() {
1213 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -07001214
Wei Wang1dc1ef52017-06-12 11:28:37 -07001215 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
1216
1217 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001218 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1219 return;
1220 }
1221
1222 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -07001223 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001224 if ((d->d_name[0] == '.')
1225 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1226 || (d->d_name[1] == '\0'))) {
1227 continue;
1228 }
1229 const std::string new_path =
1230 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1231 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1232 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1233 printf("\n");
1234 }
Wei Wang1dc1ef52017-06-12 11:28:37 -07001235 return;
Wei Wang509bb5d2017-06-09 14:42:12 -07001236}
Jayachandran Ca94c7172017-06-10 15:08:12 -07001237
1238static void DumpPacketStats() {
1239 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
Jayachandran Ca94c7172017-06-10 15:08:12 -07001240}
1241
1242static void DumpIpAddrAndRules() {
1243 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
Ray Chencbf278a2023-11-20 07:49:45 +00001244 RunCommand("NETWORK INTERFACES", {"ip", "-s", "link"});
Jayachandran Ca94c7172017-06-10 15:08:12 -07001245 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1246 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1247 RunCommand("IP RULES", {"ip", "rule", "show"});
1248 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1249}
1250
Nandana Dutt5c390032019-03-12 10:52:56 +00001251static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, int priority,
1252 std::chrono::milliseconds timeout,
1253 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001254 auto start = std::chrono::steady_clock::now();
Vishnu Naire97d6122018-01-18 13:58:56 -08001255 sp<android::IServiceManager> sm = defaultServiceManager();
1256 Dumpsys dumpsys(sm.get());
Vishnu Naire97d6122018-01-18 13:58:56 -08001257 Vector<String16> args;
1258 Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
Vishnu Naire97d6122018-01-18 13:58:56 -08001259 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1260 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001261 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001262 std::string path(title);
1263 path.append(" - ").append(String8(service).c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -08001264 size_t bytes_written = 0;
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001265 if (PropertiesHelper::IsDryRun()) {
1266 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1267 dumpsys.writeDumpFooter(STDOUT_FILENO, service, std::chrono::milliseconds(1));
1268 } else {
Devin Mooref492c1a2023-03-15 19:19:03 +00001269 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP | Dumpsys::TYPE_PID |
1270 Dumpsys::TYPE_CLIENTS | Dumpsys::TYPE_THREAD,
Devin Mooreae68df22023-02-24 20:59:51 +00001271 service, args);
1272 if (status == OK) {
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001273 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1274 std::chrono::duration<double> elapsed_seconds;
1275 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH &&
1276 service == String16("meminfo")) {
1277 // Use a longer timeout for meminfo, since 30s is not always enough.
1278 status = dumpsys.writeDump(STDOUT_FILENO, service, 60s,
1279 /* as_proto = */ false, elapsed_seconds,
1280 bytes_written);
1281 } else {
1282 status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
1283 /* as_proto = */ false, elapsed_seconds,
1284 bytes_written);
1285 }
1286 dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
1287 bool dump_complete = (status == OK);
1288 dumpsys.stopDumpThread(dump_complete);
Devin Moorecdfa4602023-03-16 20:49:39 +00001289 } else {
1290 MYLOGE("Failed to start dump thread for service: %s, status: %d",
1291 String8(service).c_str(), status);
Gavin Corkeryfac7e2b2021-07-08 22:39:02 +01001292 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001293 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001294
1295 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1296 std::chrono::steady_clock::now() - start);
1297 if (elapsed_duration > timeout) {
1298 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1299 elapsed_duration.count());
1300 break;
1301 }
1302 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001303 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001304}
1305
Vishnu Nair64afc022018-02-01 15:29:34 -08001306static void RunDumpsysText(const std::string& title, int priority,
1307 std::chrono::milliseconds timeout,
1308 std::chrono::milliseconds service_timeout) {
1309 DurationReporter duration_reporter(title);
1310 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1311 fsync(STDOUT_FILENO);
1312 RunDumpsysTextByPriority(title, priority, timeout, service_timeout);
1313}
1314
1315/* Dump all services registered with Normal or Default priority. */
Nandana Dutt5c390032019-03-12 10:52:56 +00001316static Dumpstate::RunStatus RunDumpsysTextNormalPriority(const std::string& title,
1317 std::chrono::milliseconds timeout,
1318 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001319 DurationReporter duration_reporter(title);
1320 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1321 fsync(STDOUT_FILENO);
1322 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout,
1323 service_timeout);
Nandana Dutt5c390032019-03-12 10:52:56 +00001324
1325 RETURN_IF_USER_DENIED_CONSENT();
1326
1327 return RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1328 service_timeout);
Vishnu Nair64afc022018-02-01 15:29:34 -08001329}
1330
Nandana Dutt5c390032019-03-12 10:52:56 +00001331static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priority,
1332 std::chrono::milliseconds timeout,
1333 std::chrono::milliseconds service_timeout) {
Vishnu Naire97d6122018-01-18 13:58:56 -08001334 sp<android::IServiceManager> sm = defaultServiceManager();
1335 Dumpsys dumpsys(sm.get());
1336 Vector<String16> args;
1337 Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
1338 DurationReporter duration_reporter(title);
1339
1340 auto start = std::chrono::steady_clock::now();
1341 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
1342 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001343 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001344 std::string path(kProtoPath);
1345 path.append(String8(service).c_str());
1346 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
1347 path.append("_CRITICAL");
1348 } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
1349 path.append("_HIGH");
1350 }
1351 path.append(kProtoExt);
Steven Morelandcbd69fc2021-07-20 20:45:43 +00001352 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP, service, args);
Vishnu Naire97d6122018-01-18 13:58:56 -08001353 if (status == OK) {
1354 status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
1355 bool dumpTerminated = (status == OK);
1356 dumpsys.stopDumpThread(dumpTerminated);
1357 }
1358 ZipWriter::FileEntry file_entry;
1359 ds.zip_writer_->GetLastEntry(&file_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -08001360
1361 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1362 std::chrono::steady_clock::now() - start);
1363 if (elapsed_duration > timeout) {
1364 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1365 elapsed_duration.count());
1366 break;
1367 }
1368 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001369 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001370}
1371
Nandana Dutta7db6342018-11-21 14:53:34 +00001372// Runs dumpsys on services that must dump first and will take less than 100ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001373static Dumpstate::RunStatus RunDumpsysCritical() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001374 RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1375 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Nandana Dutt5c390032019-03-12 10:52:56 +00001376
1377 RETURN_IF_USER_DENIED_CONSENT();
1378
1379 return RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1380 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Vishnu Nair780b1282017-10-10 13:57:24 -07001381}
1382
1383// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001384static Dumpstate::RunStatus RunDumpsysHigh() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001385 // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
1386 // high priority. Reduce timeout once they are able to dump in a shorter time or
1387 // moved to a parallel task.
1388 RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1389 /* timeout= */ 90s, /* service_timeout= */ 30s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001390
1391 RETURN_IF_USER_DENIED_CONSENT();
1392
1393 return RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1394 /* timeout= */ 5s, /* service_timeout= */ 1s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001395}
1396
1397// Runs dumpsys on services that must dump but can take up to 10s to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001398static Dumpstate::RunStatus RunDumpsysNormal() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001399 RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001400
1401 RETURN_IF_USER_DENIED_CONSENT();
1402
1403 return RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1404 /* timeout= */ 90s, /* service_timeout= */ 10s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001405}
1406
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001407/*
1408 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1409 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1410 * if it's not running in the parallel task.
1411 */
1412static void DumpHals(int out_fd = STDOUT_FILENO) {
Yifan Hong30528a22020-08-07 18:24:06 -07001413 RunCommand("HARDWARE HALS", {"lshal", "--all", "--types=all"},
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001414 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build(),
1415 false, out_fd);
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001416
Steven Moreland44cd9482018-01-04 16:24:13 -08001417 using android::hidl::manager::V1_0::IServiceManager;
1418 using android::hardware::defaultServiceManager;
1419
1420 sp<IServiceManager> sm = defaultServiceManager();
1421 if (sm == nullptr) {
1422 MYLOGE("Could not retrieve hwservicemanager to dump hals.\n");
1423 return;
1424 }
1425
1426 auto ret = sm->list([&](const auto& interfaces) {
1427 for (const std::string& interface : interfaces) {
1428 std::string cleanName = interface;
Steven Morelandc6b1fc22023-07-26 23:53:58 +00001429 std::replace_if(
1430 cleanName.begin(), cleanName.end(),
1431 [](char c) {
1432 return !isalnum(c) && std::string("@-_.").find(c) == std::string::npos;
1433 },
1434 '_');
Nandana Dutt979388e2018-11-30 16:48:55 +00001435 const std::string path = ds.bugreport_internal_dir_ + "/lshal_debug_" + cleanName;
Steven Moreland44cd9482018-01-04 16:24:13 -08001436
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001437 bool empty = false;
Steven Moreland44cd9482018-01-04 16:24:13 -08001438 {
1439 auto fd = android::base::unique_fd(
1440 TEMP_FAILURE_RETRY(open(path.c_str(),
1441 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1442 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1443 if (fd < 0) {
1444 MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str());
1445 continue;
1446 }
1447 RunCommandToFd(fd,
1448 "",
Steven Morelandc81cd3c2018-01-18 14:36:26 -08001449 {"lshal", "debug", "-E", interface},
Steven Moreland44cd9482018-01-04 16:24:13 -08001450 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1451
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001452 empty = 0 == lseek(fd, 0, SEEK_END);
Steven Moreland44cd9482018-01-04 16:24:13 -08001453 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001454 if (!empty) {
1455 ds.EnqueueAddZipEntryAndCleanupIfNeeded("lshal-debug/" + cleanName + ".txt",
1456 path);
1457 } else {
1458 unlink(path.c_str());
1459 }
Steven Moreland44cd9482018-01-04 16:24:13 -08001460 }
1461 });
1462
1463 if (!ret.isOk()) {
1464 MYLOGE("Could not list hals from hwservicemanager.\n");
1465 }
1466}
1467
Devin Moore8df81bb2022-06-08 22:47:02 +00001468// Dump all of the files that make up the vendor interface.
1469// See the files listed in dumpFileList() for the latest list of files.
1470static void DumpVintf() {
Devin Moore16271d92022-09-22 18:28:48 +00001471
1472 const std::string sku = android::base::GetProperty("ro.boot.product.hardware.sku", "");
1473 const auto vintfFiles = android::vintf::details::dumpFileList(sku);
Devin Moore8df81bb2022-06-08 22:47:02 +00001474 for (const auto vintfFile : vintfFiles) {
1475 struct stat st;
1476 if (stat(vintfFile.c_str(), &st) == 0) {
1477 if (S_ISDIR(st.st_mode)) {
1478 ds.AddDir(vintfFile, true /* recursive */);
1479 } else {
1480 ds.EnqueueAddZipEntryAndCleanupIfNeeded(ZIP_ROOT_DIR + vintfFile,
1481 vintfFile);
1482 }
1483 }
1484 }
1485}
1486
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001487static void DumpExternalFragmentationInfo() {
1488 struct stat st;
1489 if (stat("/proc/buddyinfo", &st) != 0) {
1490 MYLOGE("Unable to dump external fragmentation info\n");
1491 return;
1492 }
1493
1494 printf("------ EXTERNAL FRAGMENTATION INFO ------\n");
1495 std::ifstream ifs("/proc/buddyinfo");
1496 auto unusable_index_regex = std::regex{"Node\\s+([0-9]+),\\s+zone\\s+(\\S+)\\s+(.*)"};
1497 for (std::string line; std::getline(ifs, line);) {
1498 std::smatch match_results;
1499 if (std::regex_match(line, match_results, unusable_index_regex)) {
1500 std::stringstream free_pages(std::string{match_results[3]});
1501 std::vector<int> free_pages_per_order(std::istream_iterator<int>{free_pages},
1502 std::istream_iterator<int>());
1503
1504 int total_free_pages = 0;
1505 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1506 total_free_pages += (free_pages_per_order[i] * std::pow(2, i));
1507 }
1508
1509 printf("Node %s, zone %8s", match_results[1].str().c_str(),
1510 match_results[2].str().c_str());
1511
1512 int usable_free_pages = total_free_pages;
1513 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1514 auto unusable_index = (total_free_pages - usable_free_pages) /
1515 static_cast<double>(total_free_pages);
1516 printf(" %5.3f", unusable_index);
1517 usable_free_pages -= (free_pages_per_order[i] * std::pow(2, i));
1518 }
1519
1520 printf("\n");
1521 }
1522 }
1523 printf("\n");
1524}
1525
mhasankd451a472020-05-26 18:02:39 -07001526static void DumpstateLimitedOnly() {
EdenSue8fe4522023-11-20 15:37:23 +08001527 // Trimmed-down version of dumpstate to only include a allowlisted
mhasankd451a472020-05-26 18:02:39 -07001528 // set of logs (system log, event log, and system server / system app
1529 // crashes, and networking logs). See b/136273873 and b/138459828
1530 // for context.
1531 DurationReporter duration_reporter("DUMPSTATE");
1532 unsigned long timeout_ms;
1533 // calculate timeout
1534 timeout_ms = logcat_timeout({"main", "system", "crash"});
1535 RunCommand("SYSTEM LOG",
1536 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1537 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1538 timeout_ms = logcat_timeout({"events"});
1539 RunCommand(
1540 "EVENT LOG",
1541 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1542 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1543
1544 printf("========================================================\n");
1545 printf("== Networking Service\n");
1546 printf("========================================================\n");
1547
1548 RunDumpsys("DUMPSYS NETWORK_SERVICE_LIMITED", {"wifi", "-a"},
1549 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hugo Benichiaa162682020-10-30 23:28:56 +09001550 RunDumpsys("DUMPSYS CONNECTIVITY REQUESTS", {"connectivity", "requests"},
1551 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
mhasankd451a472020-05-26 18:02:39 -07001552
1553 printf("========================================================\n");
1554 printf("== Dropbox crashes\n");
1555 printf("========================================================\n");
1556
1557 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1558 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1559
1560 printf("========================================================\n");
1561 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1562 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1563 printf("========================================================\n");
1564 printf("== dumpstate: done (id %d)\n", ds.id_);
1565 printf("========================================================\n");
1566}
1567
Rhed Jaoe017f982020-07-21 17:58:41 +08001568/*
1569 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1570 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1571 * if it's not running in the parallel task.
1572 */
1573static void DumpCheckins(int out_fd = STDOUT_FILENO) {
1574 dprintf(out_fd, "========================================================\n");
1575 dprintf(out_fd, "== Checkins\n");
1576 dprintf(out_fd, "========================================================\n");
1577
1578 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"}, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001579 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"}, out_fd);
1580 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"}, out_fd);
1581 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"}, out_fd);
1582 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"}, out_fd);
1583}
1584
1585/*
1586 * Runs dumpsys on activity service to dump all application activities, services
1587 * and providers in the device.
1588 *
1589 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1590 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1591 * if it's not running in the parallel task.
1592 */
1593static void DumpAppInfos(int out_fd = STDOUT_FILENO) {
1594 dprintf(out_fd, "========================================================\n");
1595 dprintf(out_fd, "== Running Application Activities\n");
1596 dprintf(out_fd, "========================================================\n");
1597
1598 // The following dumpsys internally collects output from running apps, so it can take a long
1599 // time. So let's extend the timeout.
1600
1601 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1602
1603 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1604
1605 dprintf(out_fd, "========================================================\n");
1606 dprintf(out_fd, "== Running Application Services (platform)\n");
1607 dprintf(out_fd, "========================================================\n");
1608
1609 RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
1610 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1611
1612 dprintf(out_fd, "========================================================\n");
1613 dprintf(out_fd, "== Running Application Services (non-platform)\n");
1614 dprintf(out_fd, "========================================================\n");
1615
1616 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1617 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1618
1619 dprintf(out_fd, "========================================================\n");
1620 dprintf(out_fd, "== Running Application Providers (platform)\n");
1621 dprintf(out_fd, "========================================================\n");
1622
1623 RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
Rhed Jaob049f182021-01-11 21:08:43 +08001624 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001625
1626 dprintf(out_fd, "========================================================\n");
1627 dprintf(out_fd, "== Running Application Providers (non-platform)\n");
1628 dprintf(out_fd, "========================================================\n");
1629
1630 RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1631 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1632}
1633
Nandana Dutt5c390032019-03-12 10:52:56 +00001634// Dumps various things. Returns early with status USER_CONSENT_DENIED if user denies consent
1635// via the consent they are shown. Ignores other errors that occur while running various
1636// commands. The consent checking is currently done around long running tasks, which happen to
1637// be distributed fairly evenly throughout the function.
Kean Mariotti306633e2022-09-05 16:30:47 +00001638Dumpstate::RunStatus Dumpstate::dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001639 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001640
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001641 // Enqueue slow functions into the thread pool, if the parallel run is enabled.
Aaron Huang24d215d2022-04-27 18:51:16 +08001642 std::future<std::string> dump_hals, dump_incident_report, dump_board, dump_checkins,
Kean Mariotti306633e2022-09-05 16:30:47 +00001643 dump_netstats_report, post_process_ui_traces;
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001644 if (ds.dump_pool_) {
1645 // Pool was shutdown in DumpstateDefaultAfterCritical method in order to
Kean Mariotti306633e2022-09-05 16:30:47 +00001646 // drop root user. Restarts it.
1647 ds.dump_pool_->start(/* thread_counts = */3);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001648
Chris Morinbc223142022-02-04 14:17:11 -08001649 dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
1650 dump_incident_report = ds.dump_pool_->enqueueTask(
1651 DUMP_INCIDENT_REPORT_TASK, &DumpIncidentReport);
Aaron Huang24d215d2022-04-27 18:51:16 +08001652 dump_netstats_report = ds.dump_pool_->enqueueTask(
1653 DUMP_NETSTATS_PROTO_TASK, &DumpNetstatsProto);
Chris Morinbc223142022-02-04 14:17:11 -08001654 dump_board = ds.dump_pool_->enqueueTaskWithFd(
1655 DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
1656 dump_checkins = ds.dump_pool_->enqueueTaskWithFd(DUMP_CHECKINS_TASK, &DumpCheckins, _1);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001657 }
1658
Nandana Dutt5c390032019-03-12 10:52:56 +00001659 // Dump various things. Note that anything that takes "long" (i.e. several seconds) should
1660 // check intermittently (if it's intrerruptable like a foreach on pids) and/or should be wrapped
1661 // in a consent check (via RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK).
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001662 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001663 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001664 DumpBlockStatFiles();
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001665 DumpFile("MEMORY INFO", "/proc/meminfo");
1666 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001667 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001668
Kevin Jeon947922b2022-09-21 00:29:18 +00001669 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "BUGREPORT_PROCDUMP", {"bugreport_procdump"},
1670 CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001671
Sunny Goyal35949782019-11-19 15:54:36 -08001672 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpVisibleWindowViews);
1673
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001674 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1675 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1676 DumpFile("SLAB INFO", "/proc/slabinfo");
1677 DumpFile("ZONEINFO", "/proc/zoneinfo");
1678 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1679 DumpFile("BUDDYINFO", "/proc/buddyinfo");
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001680 DumpExternalFragmentationInfo();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001681
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001682 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001683
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001684 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001685 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001686
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001687 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001688 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_hals));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001689 } else {
1690 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_HALS_TASK, DumpHals);
1691 }
Steven Moreland81b429e2017-01-31 19:50:46 -08001692
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001693 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001694 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001695 struct stat s;
1696 if (stat("/proc/modules", &s) != 0) {
1697 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1698 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001699 RunCommand("LSMOD", {"lsmod"});
Woody Linc198f252021-05-04 16:37:11 +08001700 RunCommand("MODULES INFO",
1701 {"sh", "-c", "cat /proc/modules | cut -d' ' -f1 | "
1702 " while read MOD ; do echo modinfo:$MOD ; modinfo $MOD ; "
1703 "done"}, CommandOptions::AS_ROOT);
Felipe Lemee4eca582016-06-10 17:48:08 -07001704 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001705
Tom Cherryb87dbfa2020-07-28 11:28:53 -07001706 if (android::base::GetBoolProperty("ro.logd.kernel", false)) {
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001707 DoKernelLogcat();
1708 } else {
1709 do_dmesg();
1710 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001711
Devin Moore8df81bb2022-06-08 22:47:02 +00001712 DumpVintf();
1713
Felipe Lemef0292972016-11-22 13:57:05 -08001714 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001715
Jeff Brown1dc94e32014-09-11 14:15:27 -07001716 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001717 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001718
Jack Yu5a6b2e22020-08-14 18:13:35 +08001719 /* Dump Nfc NCI logs */
1720 ds.AddDir("/data/misc/nfc/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001721
Paul Chang0d2aad72020-02-13 20:04:03 +08001722 if (ds.options_->do_screenshot && !ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001723 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001724 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001725 }
1726
Felipe Lemee184f662016-10-27 10:04:47 -07001727 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001728
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001729 MaybeAddSystemTraceToZip();
1730
Narayan Kamath8f788292017-05-25 13:20:39 +01001731 // NOTE: tombstones are always added as separate entries in the zip archive
1732 // and are not interspersed with the main report.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001733 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
Narayan Kamathbd863722017-06-01 18:50:12 +01001734 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001735 if (!tombstones_dumped) {
1736 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001737 }
1738
Jayachandran Ca94c7172017-06-10 15:08:12 -07001739 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001740
Lorenzo Colitti807f2dd2022-05-27 12:48:37 +09001741 RunDumpsys("EBPF MAP STATS", {"connectivity", "trafficcontroller"});
Chenbo Feng276a3b62018-08-07 11:44:49 -07001742
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001743 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001744
Woody Lin20767a92022-11-29 15:50:24 +08001745 DumpShutdownCheckpoints();
1746
Jayachandran Ca94c7172017-06-10 15:08:12 -07001747 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001748
1749 dump_route_tables();
1750
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001751 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1752 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1753 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001754
Nandana Dutt5c390032019-03-12 10:52:56 +00001755 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysHigh);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001756
Chiachang Wang668ede42021-05-17 17:14:20 +08001757 // The dump mechanism in connectivity is refactored due to modularization work. Connectivity can
1758 // only register with a default priority(NORMAL priority). Dumpstate has to call connectivity
1759 // dump with priority parameters to dump high priority information.
1760 RunDumpsys("SERVICE HIGH connectivity", {"connectivity", "--dump-priority", "HIGH"},
1761 CommandOptions::WithTimeout(10).Build());
1762
Elliott Hughes23ccc622017-02-28 10:14:22 -08001763 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001764
Joe Onoratod38bc3a2023-06-29 15:48:28 -07001765 DumpFile("SYSTEM BUILD-TIME RELEASE FLAGS", "/system/etc/build_flags.json");
1766 DumpFile("SYSTEM_EXT BUILD-TIME RELEASE FLAGS", "/system_ext/etc/build_flags.json");
1767 DumpFile("PRODUCT BUILD-TIME RELEASE FLAGS", "/product/etc/build_flags.json");
1768 DumpFile("VENDOR BUILD-TIME RELEASE FLAGS", "/vendor/etc/build_flags.json");
1769
Mårten Kongstad5ad813f2023-09-28 10:09:18 +02001770 RunCommand("ACONFIG FLAGS", {PRINT_FLAGS},
1771 CommandOptions::WithTimeout(10).Always().DropRoot().Build());
Joe Onoratod38bc3a2023-06-29 15:48:28 -07001772
Jin Qianf334d662017-10-10 14:41:37 -07001773 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001774
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001775 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001776
Colin Crossf45fa6b2012-03-26 12:38:26 -07001777 /* Binder state is expensive to look at as it uses a lot of memory. */
Hridya Valsaraju920ba712020-02-09 16:27:01 -08001778 std::string binder_logs_dir = access("/dev/binderfs/binder_logs", R_OK) ?
1779 "/sys/kernel/debug/binder" : "/dev/binderfs/binder_logs";
1780
1781 DumpFile("BINDER FAILED TRANSACTION LOG", binder_logs_dir + "/failed_transaction_log");
1782 DumpFile("BINDER TRANSACTION LOG", binder_logs_dir + "/transaction_log");
1783 DumpFile("BINDER TRANSACTIONS", binder_logs_dir + "/transactions");
1784 DumpFile("BINDER STATS", binder_logs_dir + "/stats");
1785 DumpFile("BINDER STATE", binder_logs_dir + "/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001786
Yifan Hongd90cc652020-02-08 16:52:02 -08001787 ds.AddDir(SNAPSHOTCTL_LOG_DIR, false);
1788
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001789 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001790 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_board));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001791 } else {
1792 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
1793 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001794
Steven Moreland7440ddb2016-12-15 16:13:39 -08001795 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001796 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1797 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001798 // su does not exist on user builds, so try running without it.
1799 // This way any implementations of vril-dump that do not require
1800 // root can run on user builds.
1801 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001802 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001803 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001804 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001805 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001806 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001807 }
1808
Felipe Lemed8b94e52016-12-08 10:21:44 -08001809 printf("========================================================\n");
1810 printf("== Android Framework Services\n");
1811 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001812
Nandana Dutt5c390032019-03-12 10:52:56 +00001813 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001814
Jack He91ff2fe2021-02-18 18:23:43 -08001815 /* Dump Bluetooth HCI logs after getting bluetooth_manager dumpsys */
1816 ds.AddDir("/data/misc/bluetooth/logs", true);
1817
Rhed Jaoe017f982020-07-21 17:58:41 +08001818 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001819 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_checkins));
Rhed Jaoe017f982020-07-21 17:58:41 +08001820 } else {
1821 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_CHECKINS_TASK, DumpCheckins);
1822 }
Dianne Hackborn02bea972013-06-26 18:59:09 -07001823
Rhed Jaoc5f7ec32020-12-22 22:11:08 +08001824 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpAppInfos);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001825
Adrian Roos8b397ab2017-04-04 16:35:44 -07001826 printf("========================================================\n");
1827 printf("== Dropbox crashes\n");
1828 printf("========================================================\n");
1829
1830 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1831 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1832
Felipe Lemed8b94e52016-12-08 10:21:44 -08001833 printf("========================================================\n");
1834 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1835 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1836 printf("========================================================\n");
1837 printf("== dumpstate: done (id %d)\n", ds.id_);
1838 printf("========================================================\n");
Bookatz38472142018-09-28 10:20:24 -07001839
1840 printf("========================================================\n");
1841 printf("== Obtaining statsd metadata\n");
1842 printf("========================================================\n");
1843 // This differs from the usual dumpsys stats, which is the stats report data.
1844 RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
Mike Ma5c267872019-08-21 11:31:34 -07001845
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +09001846 // Add linker configuration directory
1847 ds.AddDir(LINKERCONFIG_DIR, true);
1848
Li Li830179f2022-01-04 12:53:29 -08001849 /* Dump frozen cgroupfs */
1850 dump_frozen_cgroupfs();
Li Li2eedd412021-06-30 15:11:53 -07001851
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001852 if (ds.dump_pool_) {
Aaron Huang24d215d2022-04-27 18:51:16 +08001853 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_netstats_report));
1854 } else {
1855 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_NETSTATS_PROTO_TASK,
1856 DumpNetstatsProto);
1857 }
1858
1859 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001860 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_incident_report));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001861 } else {
1862 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_INCIDENT_REPORT_TASK,
1863 DumpIncidentReport);
1864 }
Mike Ma5c267872019-08-21 11:31:34 -07001865
Kean Mariotti306633e2022-09-05 16:30:47 +00001866 MaybeAddUiTracesToZip();
1867
Nandana Dutt5c390032019-03-12 10:52:56 +00001868 return Dumpstate::RunStatus::OK;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001869}
1870
Nandana Dutt5c390032019-03-12 10:52:56 +00001871/*
1872 * Dumps state for the default case; drops root after it's no longer necessary.
1873 *
1874 * Returns RunStatus::OK if everything went fine.
1875 * Returns RunStatus::ERROR if there was an error.
1876 * Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport
1877 * with the caller.
1878 */
Jichao Lie89d9c12019-11-21 19:02:51 -08001879Dumpstate::RunStatus Dumpstate::DumpstateDefaultAfterCritical() {
Nandana Duttdb379fa2019-10-09 16:54:41 +01001880 // Capture first logcat early on; useful to take a snapshot before dumpstate logs take over the
1881 // buffer.
1882 DoLogcat();
1883 // Capture timestamp after first logcat to use in next logcat
1884 time_t logcat_ts = time(nullptr);
1885
Nandana Dutt4be45d12018-09-26 15:04:23 +01001886 /* collect stack traces from Dalvik and native processes (needs root) */
Chris Morinbc223142022-02-04 14:17:11 -08001887 std::future<std::string> dump_traces;
Rhed Jao5377d792020-07-16 17:37:39 +08001888 if (dump_pool_) {
1889 RETURN_IF_USER_DENIED_CONSENT();
1890 // One thread is enough since we only need to enqueue DumpTraces here.
1891 dump_pool_->start(/* thread_counts = */1);
1892
1893 // DumpTraces takes long time, post it to the another thread in the
1894 // pool, if pool is available
Chris Morinbc223142022-02-04 14:17:11 -08001895 dump_traces = dump_pool_->enqueueTask(
1896 DUMP_TRACES_TASK, &Dumpstate::DumpTraces, &ds, &dump_traces_path);
Rhed Jao5377d792020-07-16 17:37:39 +08001897 } else {
1898 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_TRACES_TASK, ds.DumpTraces,
1899 &dump_traces_path);
1900 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001901
1902 /* Run some operations that require root. */
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001903 if (!PropertiesHelper::IsDryRun()) {
Chris Morinc2cba7a2022-02-01 17:06:50 -08001904 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX);
1905 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX);
Woody Lin20767a92022-11-29 15:50:24 +08001906 ds.shutdown_checkpoints_ = GetDumpFds(
1907 SHUTDOWN_CHECKPOINTS_DIR, SHUTDOWN_CHECKPOINTS_FILE_PREFIX);
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001908 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001909
1910 ds.AddDir(RECOVERY_DIR, true);
1911 ds.AddDir(RECOVERY_DATA_DIR, true);
1912 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
Kelvin Zhang6eaa0f92022-09-12 09:29:19 -07001913 ds.AddDir(UPDATE_ENGINE_PREF_DIR, true);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001914 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1915 if (!PropertiesHelper::IsUserBuild()) {
1916 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1917 ds.AddDir(PROFILE_DATA_DIR_REF, true);
Calin Juravlef84d3692020-04-28 15:31:12 -07001918 ds.AddZipEntry(ZIP_ROOT_DIR + PACKAGE_DEX_USE_LIST, PACKAGE_DEX_USE_LIST);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001919 }
Jerry Changa1df8a92020-01-02 16:03:39 +08001920 ds.AddDir(PREREBOOT_DATA_DIR, false);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001921 add_mountinfo();
Peter Collingbourne78aa2942023-02-15 14:50:31 -08001922 for (const char* path : {"/proc/cpuinfo", "/proc/meminfo"}) {
1923 ds.AddZipEntry(ZIP_ROOT_DIR + path, path);
1924 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001925 DumpIpTablesAsRoot();
David Andersond9ba4752018-12-11 18:26:59 -08001926 DumpDynamicPartitionInfo();
Yifan Hong3945e1b2019-10-29 12:59:23 -07001927 ds.AddDir(OTA_METADATA_DIR, true);
Jeff Sharkey9df29d52023-02-06 14:26:30 -07001928 if (!PropertiesHelper::IsUserBuild()) {
1929 // Include dropbox entry files inside ZIP, but exclude
1930 // noisy WTF and StrictMode entries
1931 dump_files("", DROPBOX_DIR, skip_wtf_strictmode, _add_file_from_fd);
1932 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001933
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001934 // Capture any IPSec policies in play. No keys are exposed here.
Nandana Dutt4be45d12018-09-26 15:04:23 +01001935 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1936
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001937 // Dump IPsec stats. No keys are exposed here.
1938 DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
1939
Nandana Dutt4be45d12018-09-26 15:04:23 +01001940 // Run ss as root so we can see socket marks.
1941 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1942
1943 // Run iotop as root to show top 100 IO threads
1944 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1945
Erick Reyese68df822019-02-11 14:46:36 -08001946 // Gather shared memory buffer info if the product implements it
Hridya Valsaraju1da80c52021-01-09 22:10:11 -08001947 RunCommand("Dmabuf dump", {"dmabuf_dump"});
1948 RunCommand("Dmabuf per-buffer/per-exporter/per-device stats", {"dmabuf_dump", "-b"});
Erick Reyese68df822019-02-11 14:46:36 -08001949
Minchan Kim22c6a1e2019-09-30 15:58:10 -07001950 DumpFile("PSI cpu", "/proc/pressure/cpu");
1951 DumpFile("PSI memory", "/proc/pressure/memory");
1952 DumpFile("PSI io", "/proc/pressure/io");
1953
Mårten Kongstad60195a72022-09-20 14:14:20 +02001954 RunCommand("SDK EXTENSIONS", {SDK_EXT_INFO, "--dump"},
1955 CommandOptions::WithTimeout(10).Always().DropRoot().Build());
1956
Rhed Jao5377d792020-07-16 17:37:39 +08001957 if (dump_pool_) {
1958 RETURN_IF_USER_DENIED_CONSENT();
Chris Morinbc223142022-02-04 14:17:11 -08001959 WaitForTask(std::move(dump_traces));
Rhed Jao5377d792020-07-16 17:37:39 +08001960
Chris Morinbc223142022-02-04 14:17:11 -08001961 // Current running thread in the pool is the root user also. Delete
1962 // the pool and make a new one later to ensure none of threads in the pool are root.
1963 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao5377d792020-07-16 17:37:39 +08001964 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001965 if (!DropRootUser()) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001966 return Dumpstate::RunStatus::ERROR;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001967 }
1968
Nandana Dutt5c390032019-03-12 10:52:56 +00001969 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttdb379fa2019-10-09 16:54:41 +01001970 Dumpstate::RunStatus status = dumpstate();
1971 // Capture logcat since the last time we did it.
1972 DoSystemLogcat(logcat_ts);
1973 return status;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001974}
1975
Rhed Jaob5685b32020-08-14 17:19:17 +08001976// Common states for telephony and wifi which are needed to be collected before
1977// dumpstate drop the root user.
1978static void DumpstateRadioAsRoot() {
1979 DumpIpTablesAsRoot();
1980 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1981}
1982
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001983// This method collects common dumpsys for telephony and wifi. Typically, wifi
1984// reports are fine to include all information, but telephony reports on user
1985// builds need to strip some content (see DumpstateTelephonyOnly).
1986static void DumpstateRadioCommon(bool include_sensitive_info = true) {
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001987 // We need to be picky about some stuff for telephony reports on user builds.
1988 if (!include_sensitive_info) {
1989 // Only dump the radio log buffer (other buffers and dumps contain too much unrelated info).
1990 DoRadioLogcat();
1991 } else {
Rhed Jaob5685b32020-08-14 17:19:17 +08001992 // DumpHals takes long time, post it to the another thread in the pool,
1993 // if pool is available.
Chris Morinbc223142022-02-04 14:17:11 -08001994 std::future<std::string> dump_hals;
Rhed Jaob5685b32020-08-14 17:19:17 +08001995 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001996 dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
Rhed Jaob5685b32020-08-14 17:19:17 +08001997 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001998 // Contains various system properties and process startup info.
1999 do_dmesg();
2000 // Logs other than the radio buffer may contain package/component names and potential PII.
2001 DoLogcat();
2002 // Too broad for connectivity problems.
2003 DoKmsg();
Rhed Jaob5685b32020-08-14 17:19:17 +08002004 // DumpHals contains unrelated hardware info (camera, NFC, biometrics, ...).
2005 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002006 WaitForTask(std::move(dump_hals));
Rhed Jaob5685b32020-08-14 17:19:17 +08002007 } else {
2008 RUN_SLOW_FUNCTION_AND_LOG(DUMP_HALS_TASK, DumpHals);
2009 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002010 }
2011
Jayachandran Ca94c7172017-06-10 15:08:12 -07002012 DumpPacketStats();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002013 DumpIpAddrAndRules();
2014 dump_route_tables();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002015 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
2016 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08002017}
2018
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002019// We use "telephony" here for legacy reasons, though this now really means "connectivity" (cellular
2020// + wifi + networking). This method collects dumpsys for connectivity debugging only. General rules
2021// for what can be included on user builds: all reported information MUST directly relate to
2022// connectivity debugging or customer support and MUST NOT contain unrelated personally identifiable
2023// information. This information MUST NOT identify user-installed packages (UIDs are OK, package
2024// names are not), and MUST NOT contain logs of user application traffic.
2025// TODO(b/148168577) rename this and other related fields/methods to "connectivity" instead.
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08002026static void DumpstateTelephonyOnly(const std::string& calling_package) {
mukesh agrawal253dad42018-01-23 21:59:59 -08002027 DurationReporter duration_reporter("DUMPSTATE");
Jichao Lie89d9c12019-11-21 19:02:51 -08002028
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002029 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
mukesh agrawal253dad42018-01-23 21:59:59 -08002030
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002031 const bool include_sensitive_info = !PropertiesHelper::IsUserBuild();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002032
Rhed Jaob5685b32020-08-14 17:19:17 +08002033 DumpstateRadioAsRoot();
2034 if (!DropRootUser()) {
2035 return;
2036 }
2037
2038 // Starts thread pool after the root user is dropped, and two additional threads
2039 // are created for DumpHals in the DumpstateRadioCommon and DumpstateBoard.
Chris Morinbc223142022-02-04 14:17:11 -08002040 std::future<std::string> dump_board;
Rhed Jaob5685b32020-08-14 17:19:17 +08002041 if (ds.dump_pool_) {
2042 ds.dump_pool_->start(/*thread_counts =*/2);
2043
2044 // DumpstateBoard takes long time, post it to the another thread in the pool,
2045 // if pool is available.
Chris Morinbc223142022-02-04 14:17:11 -08002046 dump_board = ds.dump_pool_->enqueueTaskWithFd(
2047 DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
Rhed Jaob5685b32020-08-14 17:19:17 +08002048 }
2049
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002050 DumpstateRadioCommon(include_sensitive_info);
2051
2052 if (include_sensitive_info) {
2053 // Contains too much unrelated PII, and given the unstructured nature of sysprops, we can't
2054 // really cherrypick all of the connectivity-related ones. Apps generally have no business
2055 // reading these anyway, and there should be APIs to supply the info in a more app-friendly
2056 // way.
2057 RunCommand("SYSTEM PROPERTIES", {"getprop"});
2058 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002059
2060 printf("========================================================\n");
2061 printf("== Android Framework Services\n");
2062 printf("========================================================\n");
2063
Vishnu Nair652cc802017-11-30 15:18:30 -08002064 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2065 SEC_TO_MSEC(10));
Hunter Knepshield31cbae12021-05-11 16:23:24 -07002066 RunDumpsys("DUMPSYS", {"vcn_management"}, CommandOptions::WithTimeout(90).Build(),
2067 SEC_TO_MSEC(10));
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08002068 if (include_sensitive_info) {
2069 // Carrier apps' services will be dumped below in dumpsys activity service all-non-platform.
2070 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
2071 SEC_TO_MSEC(10));
2072 } else {
2073 // If the caller is a carrier app and has a carrier service, dump it here since we aren't
2074 // running dumpsys activity service all-non-platform below. Due to the increased output, we
2075 // give a higher timeout as well.
2076 RunDumpsys("DUMPSYS", {"carrier_config", "--requesting-package", calling_package},
2077 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(30));
2078 }
2079 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002080 RunDumpsys("DUMPSYS", {"netpolicy"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2081 RunDumpsys("DUMPSYS", {"network_management"}, CommandOptions::WithTimeout(90).Build(),
Sooraj Sasindrane8d98912018-04-20 11:31:55 -07002082 SEC_TO_MSEC(10));
Hunter Knepshield0fe51b12020-03-05 16:58:20 -08002083 RunDumpsys("DUMPSYS", {"telephony.registry"}, CommandOptions::WithTimeout(90).Build(),
2084 SEC_TO_MSEC(10));
Jack Yu773cc032023-03-16 22:43:39 -07002085 RunDumpsys("DUMPSYS", {"isub"}, CommandOptions::WithTimeout(90).Build(),
2086 SEC_TO_MSEC(10));
Grant Menke56698972023-02-24 13:11:07 -08002087 RunDumpsys("DUMPSYS", {"telecom"}, CommandOptions::WithTimeout(90).Build(),
2088 SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002089 if (include_sensitive_info) {
2090 // Contains raw IP addresses, omit from reports on user builds.
2091 RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2092 // Contains raw destination IP/MAC addresses, omit from reports on user builds.
2093 RunDumpsys("DUMPSYS", {"connmetrics"}, CommandOptions::WithTimeout(90).Build(),
2094 SEC_TO_MSEC(10));
2095 // Contains package/component names, omit from reports on user builds.
2096 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
2097 SEC_TO_MSEC(10));
2098 // Contains package names, but should be relatively simple to remove them (also contains
2099 // UIDs already), omit from reports on user builds.
2100 RunDumpsys("BATTERYSTATS", {"deviceidle"}, CommandOptions::WithTimeout(90).Build(),
2101 SEC_TO_MSEC(10));
2102 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002103
2104 printf("========================================================\n");
2105 printf("== Running Application Services\n");
2106 printf("========================================================\n");
2107
2108 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
2109
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002110 if (include_sensitive_info) {
2111 printf("========================================================\n");
2112 printf("== Running Application Services (non-platform)\n");
2113 printf("========================================================\n");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002114
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002115 // Contains package/component names and potential PII, omit from reports on user builds.
2116 // To get dumps of the active CarrierService(s) on user builds, we supply an argument to the
2117 // carrier_config dumpsys instead.
2118 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
2119 DUMPSYS_COMPONENTS_OPTIONS);
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002120
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002121 printf("========================================================\n");
2122 printf("== Checkins\n");
2123 printf("========================================================\n");
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002124
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002125 // Contains package/component names, omit from reports on user builds.
2126 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
2127 }
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002128
2129 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07002130 printf("== dumpstate: done (id %d)\n", ds.id_);
2131 printf("========================================================\n");
Rhed Jaob5685b32020-08-14 17:19:17 +08002132
2133 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002134 WaitForTask(std::move(dump_board));
Rhed Jaob5685b32020-08-14 17:19:17 +08002135 } else {
2136 RUN_SLOW_FUNCTION_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
2137 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002138}
2139
mukesh agrawal253dad42018-01-23 21:59:59 -08002140// This method collects dumpsys for wifi debugging only
2141static void DumpstateWifiOnly() {
2142 DurationReporter duration_reporter("DUMPSTATE");
2143
Rhed Jaob5685b32020-08-14 17:19:17 +08002144 DumpstateRadioAsRoot();
2145 if (!DropRootUser()) {
2146 return;
2147 }
2148
2149 // Starts thread pool after the root user is dropped. Only one additional
2150 // thread is needed for DumpHals in the DumpstateRadioCommon.
2151 if (ds.dump_pool_) {
2152 ds.dump_pool_->start(/*thread_counts =*/1);
2153 }
2154
mukesh agrawal253dad42018-01-23 21:59:59 -08002155 DumpstateRadioCommon();
2156
2157 printf("========================================================\n");
2158 printf("== Android Framework Services\n");
2159 printf("========================================================\n");
2160
2161 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2162 SEC_TO_MSEC(10));
2163 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
2164 SEC_TO_MSEC(10));
2165
2166 printf("========================================================\n");
2167 printf("== dumpstate: done (id %d)\n", ds.id_);
2168 printf("========================================================\n");
2169}
2170
Elis Elliott8e401ad2023-08-08 11:18:59 +00002171// Collects a lightweight dumpstate to be used for debugging onboarding related flows.
2172static void DumpstateOnboardingOnly() {
2173 ds.AddDir(LOGPERSIST_DATA_DIR, false);
2174}
2175
Nandana Duttcf419a72019-03-14 10:40:17 +00002176Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
Gavin Corkery789d7a52021-02-24 23:52:35 +00002177 const std::string temp_file_pattern = ds.bugreport_internal_dir_ + "/dumptrace_XXXXXX";
Nandana Duttfaafd522019-03-11 09:23:09 +00002178 const size_t buf_size = temp_file_pattern.length() + 1;
2179 std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
2180 memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
2181
2182 // Create a new, empty file to receive all trace dumps.
2183 //
2184 // TODO: This can be simplified once we remove support for the old style
2185 // dumps. We can have a file descriptor passed in to dump_traces instead
2186 // of creating a file, closing it and then reopening it again.
2187 android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
2188 if (fd < 0) {
2189 MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002190 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002191 }
2192
2193 // Nobody should have access to this temporary file except dumpstate, but we
2194 // temporarily grant 'read' to 'others' here because this file is created
2195 // when tombstoned is still running as root, but dumped after dropping. This
2196 // can go away once support for old style dumping has.
2197 const int chmod_ret = fchmod(fd, 0666);
2198 if (chmod_ret < 0) {
2199 MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002200 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002201 }
2202
2203 std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
2204 if (proc.get() == nullptr) {
2205 MYLOGE("opendir /proc failed: %s\n", strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002206 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002207 }
2208
2209 // Number of times process dumping has timed out. If we encounter too many
2210 // failures, we'll give up.
2211 int timeout_failures = 0;
2212 bool dalvik_found = false;
2213
Jayant Chowdharya0a8eb22022-05-20 03:30:09 +00002214 const std::set<int> hal_pids = get_interesting_pids();
Nandana Duttfaafd522019-03-11 09:23:09 +00002215
2216 struct dirent* d;
2217 while ((d = readdir(proc.get()))) {
Nandana Duttcf419a72019-03-14 10:40:17 +00002218 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttfaafd522019-03-11 09:23:09 +00002219 int pid = atoi(d->d_name);
2220 if (pid <= 0) {
2221 continue;
2222 }
2223
Kevin Jeond0f8a982023-04-07 14:27:11 -04002224 // Skip cached processes.
2225 if (IsCached(pid)) {
2226 // For consistency, the header and footer to this message match those
2227 // dumped by debuggerd in the success case.
2228 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
2229 dprintf(fd, "Dump skipped for cached process.\n");
2230 dprintf(fd, "---- end %d ----", pid);
2231 continue;
2232 }
2233
Nandana Duttfaafd522019-03-11 09:23:09 +00002234 const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
2235 std::string exe;
2236 if (!android::base::Readlink(link_name, &exe)) {
2237 continue;
2238 }
2239
2240 bool is_java_process;
2241 if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
2242 // Don't bother dumping backtraces for the zygote.
2243 if (IsZygote(pid)) {
2244 continue;
2245 }
2246
2247 dalvik_found = true;
2248 is_java_process = true;
2249 } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
2250 is_java_process = false;
2251 } else {
2252 // Probably a native process we don't care about, continue.
2253 continue;
2254 }
2255
2256 // If 3 backtrace dumps fail in a row, consider debuggerd dead.
2257 if (timeout_failures == 3) {
2258 dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
2259 break;
2260 }
2261
2262 const uint64_t start = Nanotime();
2263 const int ret = dump_backtrace_to_file_timeout(
Kevin Jeonb8a39362023-04-04 15:00:34 -04002264 pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace, 3, fd);
Nandana Duttfaafd522019-03-11 09:23:09 +00002265
2266 if (ret == -1) {
2267 // For consistency, the header and footer to this message match those
2268 // dumped by debuggerd in the success case.
2269 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
2270 dprintf(fd, "Dump failed, likely due to a timeout.\n");
2271 dprintf(fd, "---- end %d ----", pid);
2272 timeout_failures++;
2273 continue;
2274 }
2275
2276 // We've successfully dumped stack traces, reset the failure count
2277 // and write a summary of the elapsed time to the file and continue with the
2278 // next process.
2279 timeout_failures = 0;
2280
2281 dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
2282 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
2283 }
2284
2285 if (!dalvik_found) {
2286 MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
2287 }
2288
Nandana Duttcf419a72019-03-14 10:40:17 +00002289 *path = file_name_buf.release();
2290 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002291}
2292
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002293static dumpstate_hal_hidl::DumpstateMode GetDumpstateHalModeHidl(
2294 const Dumpstate::BugreportMode bugreport_mode) {
2295 switch (bugreport_mode) {
2296 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2297 return dumpstate_hal_hidl::DumpstateMode::FULL;
2298 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2299 return dumpstate_hal_hidl::DumpstateMode::INTERACTIVE;
2300 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2301 return dumpstate_hal_hidl::DumpstateMode::REMOTE;
2302 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2303 return dumpstate_hal_hidl::DumpstateMode::WEAR;
2304 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2305 return dumpstate_hal_hidl::DumpstateMode::CONNECTIVITY;
2306 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2307 return dumpstate_hal_hidl::DumpstateMode::WIFI;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002308 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002309 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2310 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2311 }
2312 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2313}
2314
2315static dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode GetDumpstateHalModeAidl(
2316 const Dumpstate::BugreportMode bugreport_mode) {
2317 switch (bugreport_mode) {
2318 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2319 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::FULL;
2320 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2321 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::INTERACTIVE;
2322 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2323 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::REMOTE;
2324 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2325 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WEAR;
2326 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2327 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::CONNECTIVITY;
2328 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2329 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WIFI;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002330 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002331 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2332 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2333 }
2334 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2335}
2336
2337static void DoDumpstateBoardHidl(
2338 const sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_1_0,
2339 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2340 const Dumpstate::BugreportMode bugreport_mode,
2341 const size_t timeout_sec) {
2342
2343 using ScopedNativeHandle =
2344 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
2345 ScopedNativeHandle handle(native_handle_create(static_cast<int>(dumpstate_fds.size()), 0),
2346 [](native_handle_t* handle) {
2347 // we don't close file handle's here
2348 // via native_handle_close(handle)
2349 // instead we let dumpstate_fds close the file handles when
2350 // dumpstate_fds gets destroyed
2351 native_handle_delete(handle);
2352 });
2353 if (handle == nullptr) {
2354 MYLOGE("Could not create native_handle for dumpstate HAL\n");
2355 return;
2356 }
2357
2358 for (size_t i = 0; i < dumpstate_fds.size(); i++) {
2359 handle.get()->data[i] = dumpstate_fds[i].get();
2360 }
2361
2362 // Prefer version 1.1 if available. New devices launching with R are no longer allowed to
2363 // implement just 1.0.
2364 const char* descriptor_to_kill;
2365 using DumpstateBoardTask = std::packaged_task<bool()>;
2366 DumpstateBoardTask dumpstate_board_task;
2367 sp<dumpstate_hal_hidl::IDumpstateDevice> dumpstate_hal(
2368 dumpstate_hal_hidl::IDumpstateDevice::castFrom(dumpstate_hal_1_0));
2369 if (dumpstate_hal != nullptr) {
2370 MYLOGI("Using IDumpstateDevice v1.1 HIDL HAL");
2371
2372 dumpstate_hal_hidl::DumpstateMode dumpstate_hal_mode =
2373 GetDumpstateHalModeHidl(bugreport_mode);
2374
2375 descriptor_to_kill = dumpstate_hal_hidl::IDumpstateDevice::descriptor;
2376 dumpstate_board_task =
2377 DumpstateBoardTask([timeout_sec, dumpstate_hal_mode, dumpstate_hal, &handle]() -> bool {
2378 ::android::hardware::Return<dumpstate_hal_hidl::DumpstateStatus> status =
2379 dumpstate_hal->dumpstateBoard_1_1(handle.get(), dumpstate_hal_mode,
2380 SEC_TO_MSEC(timeout_sec));
2381 if (!status.isOk()) {
2382 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2383 return false;
2384 } else if (status != dumpstate_hal_hidl::DumpstateStatus::OK) {
2385 MYLOGE("dumpstateBoard failed with DumpstateStatus::%s\n",
2386 dumpstate_hal_hidl::toString(status).c_str());
2387 return false;
2388 }
2389 return true;
2390 });
2391 } else {
2392 MYLOGI("Using IDumpstateDevice v1.0 HIDL HAL");
2393
2394 descriptor_to_kill = dumpstate_hal_hidl_1_0::IDumpstateDevice::descriptor;
2395 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal_1_0, &handle]() -> bool {
2396 ::android::hardware::Return<void> status =
2397 dumpstate_hal_1_0->dumpstateBoard(handle.get());
2398 if (!status.isOk()) {
2399 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2400 return false;
2401 }
2402 return true;
2403 });
2404 }
2405 auto result = dumpstate_board_task.get_future();
2406 std::thread(std::move(dumpstate_board_task)).detach();
2407
2408 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2409 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2410 if (!android::base::SetProperty(
2411 "ctl.interface_restart",
2412 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2413 MYLOGE("Couldn't restart dumpstate HAL\n");
2414 }
2415 }
2416 // Wait some time for init to kill dumpstate vendor HAL
2417 constexpr size_t killing_timeout_sec = 10;
2418 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2419 MYLOGE(
2420 "killing dumpstateBoard timed out after %zus, continue and "
2421 "there might be racing in content\n",
2422 killing_timeout_sec);
2423 }
2424}
2425
2426static void DoDumpstateBoardAidl(
2427 const std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal,
2428 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2429 const Dumpstate::BugreportMode bugreport_mode, const size_t timeout_sec) {
2430 MYLOGI("Using IDumpstateDevice AIDL HAL");
2431
2432 const char* descriptor_to_kill;
2433 using DumpstateBoardTask = std::packaged_task<bool()>;
2434 DumpstateBoardTask dumpstate_board_task;
2435 dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode dumpstate_hal_mode =
2436 GetDumpstateHalModeAidl(bugreport_mode);
2437
2438 descriptor_to_kill = dumpstate_hal_aidl::IDumpstateDevice::descriptor;
2439 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal, &dumpstate_fds, dumpstate_hal_mode,
2440 timeout_sec]() -> bool {
2441 auto status = dumpstate_hal->dumpstateBoard(dumpstate_fds, dumpstate_hal_mode, timeout_sec);
2442
2443 if (!status.isOk()) {
2444 MYLOGE("dumpstateBoard failed: %s\n", status.getDescription().c_str());
2445 return false;
2446 }
2447 return true;
2448 });
2449 auto result = dumpstate_board_task.get_future();
2450 std::thread(std::move(dumpstate_board_task)).detach();
2451
2452 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2453 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2454 if (!android::base::SetProperty(
2455 "ctl.interface_restart",
2456 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2457 MYLOGE("Couldn't restart dumpstate HAL\n");
2458 }
2459 }
2460 // Wait some time for init to kill dumpstate vendor HAL
2461 constexpr size_t killing_timeout_sec = 10;
2462 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2463 MYLOGE(
2464 "killing dumpstateBoard timed out after %zus, continue and "
2465 "there might be racing in content\n",
2466 killing_timeout_sec);
2467 }
2468}
2469
2470static std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> GetDumpstateBoardAidlService() {
2471 const std::string aidl_instance_name =
2472 std::string(dumpstate_hal_aidl::IDumpstateDevice::descriptor) + "/default";
2473
2474 if (!AServiceManager_isDeclared(aidl_instance_name.c_str())) {
2475 return nullptr;
2476 }
2477
2478 ndk::SpAIBinder dumpstateBinder(AServiceManager_waitForService(aidl_instance_name.c_str()));
2479
2480 return dumpstate_hal_aidl::IDumpstateDevice::fromBinder(dumpstateBinder);
2481}
2482
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002483void Dumpstate::DumpstateBoard(int out_fd) {
2484 dprintf(out_fd, "========================================================\n");
2485 dprintf(out_fd, "== Board\n");
2486 dprintf(out_fd, "========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08002487
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002488 /*
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002489 * mount debugfs for non-user builds with ro.product.debugfs_restrictions.enabled
Hridya Valsaraju51101602021-04-02 14:32:46 -07002490 * set to true and unmount it after invoking dumpstateBoard_* methods.
2491 * This is to enable debug builds to not have debugfs mounted during runtime.
2492 * It will also ensure that debugfs is only accessed by the dumpstate HAL.
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002493 */
Hridya Valsaraju51101602021-04-02 14:32:46 -07002494 auto mount_debugfs =
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002495 android::base::GetBoolProperty("ro.product.debugfs_restrictions.enabled", false);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002496 if (mount_debugfs) {
2497 RunCommand("mount debugfs", {"mount", "-t", "debugfs", "debugfs", "/sys/kernel/debug"},
2498 AS_ROOT_20);
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002499 RunCommand("chmod debugfs", {"chmod", "0755", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002500 }
2501
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002502 std::vector<std::string> paths;
2503 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07002504 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002505 paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
2506 kDumpstateBoardFiles[i].c_str()));
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002507 remover.emplace_back(android::base::make_scope_guard(
2508 std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002509 }
Jie Song9fbfad02017-06-20 16:29:42 -07002510
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002511 // get dumpstate HAL AIDL implementation
2512 std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal_handle_aidl(
2513 GetDumpstateBoardAidlService());
2514 if (dumpstate_hal_handle_aidl == nullptr) {
2515 MYLOGI("No IDumpstateDevice AIDL implementation\n");
2516 }
2517
2518 // get dumpstate HAL HIDL implementation, only if AIDL HAL implementation not found
2519 sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_handle_hidl_1_0 = nullptr;
2520 if (dumpstate_hal_handle_aidl == nullptr) {
2521 dumpstate_hal_handle_hidl_1_0 = dumpstate_hal_hidl_1_0::IDumpstateDevice::getService();
2522 if (dumpstate_hal_handle_hidl_1_0 == nullptr) {
2523 MYLOGI("No IDumpstateDevice HIDL implementation\n");
2524 }
2525 }
2526
2527 // if neither HIDL nor AIDL implementation found, then return
2528 if (dumpstate_hal_handle_hidl_1_0 == nullptr && dumpstate_hal_handle_aidl == nullptr) {
2529 MYLOGE("Could not find IDumpstateDevice implementation\n");
Wei Wang587eac92018-04-05 12:17:20 -07002530 return;
2531 }
2532
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002533 // this is used to hold the file descriptors and when this variable goes out of scope
2534 // the file descriptors are closed
2535 std::vector<::ndk::ScopedFileDescriptor> dumpstate_fds;
Wei Wang587eac92018-04-05 12:17:20 -07002536
Nandana Dutt5c390032019-03-12 10:52:56 +00002537 // TODO(128270426): Check for consent in between?
Wei Wang587eac92018-04-05 12:17:20 -07002538 for (size_t i = 0; i < paths.size(); i++) {
2539 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
2540
2541 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
2542 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
2543 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
2544 if (fd < 0) {
2545 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
2546 return;
2547 }
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002548
2549 dumpstate_fds.emplace_back(fd.release());
2550 // we call fd.release() here to make sure "fd" does not get closed
2551 // after "fd" goes out of scope after this block.
2552 // "fd" will be closed when "dumpstate_fds" goes out of scope
2553 // i.e. when we exit this function
Wei Wang587eac92018-04-05 12:17:20 -07002554 }
2555
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002556 // Given that bugreport is required to diagnose failures, it's better to set an arbitrary amount
2557 // of timeout for IDumpstateDevice than to block the rest of bugreport. In the timeout case, we
2558 // will kill the HAL and grab whatever it dumped in time.
Michael Eastwood8523ea02022-03-10 16:33:08 -08002559 constexpr size_t timeout_sec = 45;
Wei Wang587eac92018-04-05 12:17:20 -07002560
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002561 if (dumpstate_hal_handle_aidl != nullptr) {
2562 DoDumpstateBoardAidl(dumpstate_hal_handle_aidl, dumpstate_fds, options_->bugreport_mode,
2563 timeout_sec);
2564 } else if (dumpstate_hal_handle_hidl_1_0 != nullptr) {
2565 // run HIDL HAL only if AIDL HAL not found
2566 DoDumpstateBoardHidl(dumpstate_hal_handle_hidl_1_0, dumpstate_fds, options_->bugreport_mode,
2567 timeout_sec);
Wei Wang587eac92018-04-05 12:17:20 -07002568 }
2569
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002570 if (mount_debugfs) {
Hridya Valsaraju51101602021-04-02 14:32:46 -07002571 auto keep_debugfs_mounted =
2572 android::base::GetProperty("persist.dbg.keep_debugfs_mounted", "");
2573 if (keep_debugfs_mounted.empty())
2574 RunCommand("unmount debugfs", {"umount", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002575 }
2576
Wei Wang587eac92018-04-05 12:17:20 -07002577 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
2578 for (size_t i = 0; i < paths.size(); i++) {
2579 struct stat s;
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002580 if (fstat(dumpstate_fds[i].get(), &s) == -1) {
2581 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(), strerror(errno));
Wei Wang587eac92018-04-05 12:17:20 -07002582 file_sizes[i] = -1;
2583 continue;
2584 }
2585 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002586 }
2587
2588 for (size_t i = 0; i < paths.size(); i++) {
2589 if (file_sizes[i] == -1) {
2590 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002591 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002592 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07002593 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002594 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002595 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002596 remover[i].Disable();
2597 EnqueueAddZipEntryAndCleanupIfNeeded(kDumpstateBoardFiles[i], paths[i]);
2598 dprintf(out_fd, "*** See %s entry ***\n", kDumpstateBoardFiles[i].c_str());
Jie Song9fbfad02017-06-20 16:29:42 -07002599 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08002600}
2601
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002602static void ShowUsage() {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002603 fprintf(stderr,
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002604 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o directory] [-p] "
2605 "[-s] [-S] [-q] [-P] [-R] [-L] [-V version]\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002606 " -h: display this help message\n"
2607 " -b: play sound file instead of vibrate, at beginning of job\n"
2608 " -e: play sound file instead of vibrate, at end of job\n"
mhasank2d75c442020-06-11 15:05:25 -07002609 " -o: write to custom directory (only in limited mode)\n"
Abhijeet Kaurbb55a3b2019-06-13 18:07:25 +01002610 " -p: capture screenshot to filename.png\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002611 " -s: write zipped file to control socket (for init)\n"
2612 " -S: write file location to control socket (for init)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002613 " -q: disable vibrate\n"
Abhijeet Kaure370d682019-10-01 16:49:30 +01002614 " -P: send broadcast when started and do progress updates\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002615 " -R: take bugreport in remote mode (shouldn't be used with -P)\n"
Nandana Dutt235864b2019-01-22 12:10:16 +00002616 " -w: start binder service and make it wait for a call to startBugreport\n"
mhasankd451a472020-05-26 18:02:39 -07002617 " -L: output limited information that is safe for submission in feedback reports\n"
Felipe Lemed071c682016-10-20 16:48:00 -07002618 " -v: prints the dumpstate header and exit\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002619}
2620
Wei Liuf87959e2016-08-26 14:51:42 -07002621static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07002622 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07002623}
2624
Felipe Leme1d486fe2016-10-14 18:06:47 -07002625bool Dumpstate::FinishZipFile() {
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002626 // Runs all enqueued adding zip entry and cleanup tasks before finishing the zip file.
2627 if (zip_entry_tasks_) {
2628 zip_entry_tasks_->run(/* do_cancel = */false);
2629 }
2630
Felipe Leme9a523ae2016-10-20 15:10:33 -07002631 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07002632 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07002633 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002634 // Final timestamp
2635 char date[80];
2636 time_t the_real_now_please_stand_up = time(nullptr);
2637 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002638 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002639 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002640
Felipe Leme9a523ae2016-10-20 15:10:33 -07002641 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002642 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08002643 return false;
2644 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07002645 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002646 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08002647 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08002648 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08002649
Felipe Leme0f3fb202016-06-10 17:10:53 -07002650 // Add log file (which contains stderr output) to zip...
2651 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002652 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07002653 MYLOGE("Failed to add dumpstate log to .zip file\n");
2654 return false;
2655 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002656 // TODO: Should truncate the existing file.
2657 // ... and re-open it for further logging.
Nandana Dutta344cb62019-02-22 15:12:35 +00002658 if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
2659 return false;
2660 }
Felipe Leme0f3fb202016-06-10 17:10:53 -07002661 fprintf(stderr, "\n");
2662
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002663 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07002664 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002665 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002666 return false;
2667 }
2668
Felipe Leme1d486fe2016-10-14 18:06:47 -07002669 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
2670 ds.zip_file.reset(nullptr);
2671
Felipe Lemee9d2c542016-11-15 11:48:26 -08002672 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002673 android::os::UnlinkAndLogOnError(tmp_path_);
Felipe Lemec4eee562016-04-21 15:42:55 -07002674
Felipe Leme1e9edc62015-12-21 16:02:13 -08002675 return true;
2676}
Felipe Leme6e01fa62015-11-11 19:35:14 -08002677
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00002678static void SendBroadcast(const std::string& action,
2679 const std::vector<std::string>& args,
2680 int32_t user_id) {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002681 // clang-format off
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00002682 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user",
2683 std::to_string(user_id), "--receiver-foreground",
2684 "--receiver-include-background", "-a", action};
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002685 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08002686
2687 am.insert(am.end(), args.begin(), args.end());
2688
Felipe Leme8d2410e2017-02-08 09:46:08 -08002689 RunCommand("", am,
2690 CommandOptions::WithTimeout(20)
2691 .Log("Sending broadcast: '%s'\n")
2692 .Always()
2693 .DropRoot()
2694 .RedirectStderr()
2695 .Build());
2696}
2697
Felipe Leme35b8cf12017-02-10 15:47:29 -08002698static void Vibrate(int duration_ms) {
2699 // clang-format off
Lais Andrade51156962021-02-22 19:21:35 +00002700 std::vector<std::string> args = {"cmd", "vibrator_manager", "synced", "-f", "-d", "dumpstate",
2701 "oneshot", std::to_string(duration_ms)};
2702 RunCommand("", args,
Felipe Leme35b8cf12017-02-10 15:47:29 -08002703 CommandOptions::WithTimeout(10)
2704 .Log("Vibrate: '%s'\n")
2705 .Always()
2706 .Build());
2707 // clang-format on
2708}
2709
Nandana Dutt979388e2018-11-30 16:48:55 +00002710static void MaybeResolveSymlink(std::string* path) {
2711 std::string resolved_path;
2712 if (android::base::Readlink(*path, &resolved_path)) {
2713 *path = resolved_path;
2714 }
2715}
2716
Nandana Dutt4be45d12018-09-26 15:04:23 +01002717/*
2718 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002719 * and adds the version file. Return false if zip_file could not be open to write.
Nandana Dutt4be45d12018-09-26 15:04:23 +01002720 */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002721static bool PrepareToWriteToFile() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002722 MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2723
Nandana Dutt4be45d12018-09-26 15:04:23 +01002724 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2725 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002726 ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002727 char date[80];
2728 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2729 ds.name_ = date;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002730
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002731 if (ds.options_->telephony_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002732 ds.base_name_ += "-telephony";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002733 } else if (ds.options_->wifi_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002734 ds.base_name_ += "-wifi";
2735 }
2736
Paul Chang0d2aad72020-02-13 20:04:03 +08002737 if (ds.options_->do_screenshot) {
Nandana Dutt9d17b942020-03-26 10:02:59 +00002738 ds.screenshot_path_ = ds.GetPath(ds.CalledByApi() ? "-png.tmp" : ".png");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002739 }
2740 ds.tmp_path_ = ds.GetPath(".tmp");
2741 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2742
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01002743 std::string destination = ds.CalledByApi()
Nandana Dutt54dbd672019-01-11 12:58:05 +00002744 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
Nandana Dutt9a76d202019-01-21 15:56:48 +00002745 : ds.bugreport_internal_dir_.c_str();
Nandana Dutt4be45d12018-09-26 15:04:23 +01002746 MYLOGD(
Nandana Dutt235c6672019-11-14 15:22:32 +00002747 "Bugreport dir: [%s] "
2748 "Base name: [%s] "
2749 "Suffix: [%s] "
2750 "Log path: [%s] "
2751 "Temporary path: [%s] "
2752 "Screenshot path: [%s]\n",
Nandana Dutt9a76d202019-01-21 15:56:48 +00002753 destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2754 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002755
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002756 ds.path_ = ds.GetPath(ds.CalledByApi() ? "-zip.tmp" : ".zip");
2757 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2758 create_parent_dirs(ds.path_.c_str());
2759 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2760 if (ds.zip_file == nullptr) {
2761 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2762 return false;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002763 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002764 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2765 ds.AddTextZipEntry("version.txt", ds.version_);
2766 return true;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002767}
2768
2769/*
Abhijeet Kaure370d682019-10-01 16:49:30 +01002770 * Finalizes writing to the file by zipping the tmp file to the final location,
Nandana Dutt4be45d12018-09-26 15:04:23 +01002771 * printing zipped file status, etc.
2772 */
2773static void FinalizeFile() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002774 bool do_text_file = !ds.FinishZipFile();
2775 if (do_text_file) {
2776 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002777 }
mhasank2d75c442020-06-11 15:05:25 -07002778
2779 std::string final_path = ds.path_;
2780 if (ds.options_->OutputToCustomFile()) {
mhasank3a4cfb42020-06-15 18:06:43 -07002781 final_path = ds.GetPath(ds.options_->out_dir, ".zip");
mhasank2d75c442020-06-11 15:05:25 -07002782 android::os::CopyFileToFile(ds.path_, final_path);
2783 }
2784
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002785 if (ds.options_->stream_to_socket) {
2786 android::os::CopyFileToFd(ds.path_, ds.control_socket_fd_);
2787 } else if (ds.options_->progress_updates_to_socket) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002788 if (do_text_file) {
2789 dprintf(ds.control_socket_fd_,
2790 "FAIL:could not create zip file, check %s "
2791 "for more details\n",
2792 ds.log_path_.c_str());
2793 } else {
mhasank2d75c442020-06-11 15:05:25 -07002794 dprintf(ds.control_socket_fd_, "OK:%s\n", final_path.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002795 }
2796 }
2797}
2798
Nandana Dutt4be45d12018-09-26 15:04:23 +01002799
Nandana Dutt58d72e22018-11-16 10:30:48 +00002800static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2801 switch (mode) {
2802 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2803 return "BUGREPORT_FULL";
2804 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2805 return "BUGREPORT_INTERACTIVE";
2806 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2807 return "BUGREPORT_REMOTE";
2808 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2809 return "BUGREPORT_WEAR";
2810 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2811 return "BUGREPORT_TELEPHONY";
2812 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2813 return "BUGREPORT_WIFI";
Elis Elliott8e401ad2023-08-08 11:18:59 +00002814 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
2815 return "BUGREPORT_ONBOARDING";
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002816 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2817 return "BUGREPORT_DEFAULT";
Nandana Dutt58d72e22018-11-16 10:30:48 +00002818 }
2819}
2820
Steven Leeb573eb82022-11-29 22:31:35 +08002821static bool IsConsentlessBugreportAllowed(const Dumpstate::DumpOptions& options) {
2822 // only BUGREPORT_TELEPHONY does not allow using consentless bugreport
2823 return !options.telephony_only;
2824}
2825
Paul Changf59c2b72020-03-10 02:08:55 +08002826static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options,
2827 bool is_screenshot_requested) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002828 // Modify com.android.shell.BugreportProgressService#isDefaultScreenshotRequired as well for
2829 // default system screenshots.
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002830 options->bugreport_mode = mode;
2831 options->bugreport_mode_string = ModeToString(mode);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002832 switch (mode) {
2833 case Dumpstate::BugreportMode::BUGREPORT_FULL:
Paul Changf59c2b72020-03-10 02:08:55 +08002834 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002835 break;
2836 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002837 // Currently, the dumpstate binder is only used by Shell to update progress.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002838 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002839 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002840 break;
2841 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002842 options->do_vibrate = false;
2843 options->is_remote_mode = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002844 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002845 break;
2846 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
Robert Ginda55ecebd2023-04-03 22:53:13 +00002847 options->do_vibrate = false;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002848 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002849 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002850 break;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002851 // TODO(b/148168577) rename TELEPHONY everywhere to CONNECTIVITY.
Nandana Dutt58d72e22018-11-16 10:30:48 +00002852 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002853 options->telephony_only = true;
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002854 options->do_progress_updates = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002855 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002856 break;
2857 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002858 options->wifi_only = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002859 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002860 break;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002861 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
2862 options->onboarding_only = true;
2863 options->do_screenshot = false;
2864 break;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002865 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2866 break;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002867 }
2868}
2869
Nandana Dutt58d72e22018-11-16 10:30:48 +00002870static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
Nandana Dutt235c6672019-11-14 15:22:32 +00002871 MYLOGI(
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002872 "do_vibrate: %d stream_to_socket: %d progress_updates_to_socket: %d do_screenshot: %d "
Rhed Jao25f50e02020-08-20 00:10:32 +08002873 "is_remote_mode: %d show_header_only: %d telephony_only: %d "
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002874 "wifi_only: %d do_progress_updates: %d fd: %d bugreport_mode: %s "
mhasankd451a472020-05-26 18:02:39 -07002875 "limited_only: %d args: %s\n",
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002876 options.do_vibrate, options.stream_to_socket, options.progress_updates_to_socket,
Paul Chang0d2aad72020-02-13 20:04:03 +08002877 options.do_screenshot, options.is_remote_mode, options.show_header_only,
Rhed Jao25f50e02020-08-20 00:10:32 +08002878 options.telephony_only, options.wifi_only,
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002879 options.do_progress_updates, options.bugreport_fd.get(),
2880 options.bugreport_mode_string.c_str(),
2881 options.limited_only, options.args.c_str());
Nandana Dutt58d72e22018-11-16 10:30:48 +00002882}
2883
Nandana Dutt54dbd672019-01-11 12:58:05 +00002884void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
Kean Mariotti306633e2022-09-05 16:30:47 +00002885 int bugreport_flags,
Nandana Dutt54dbd672019-01-11 12:58:05 +00002886 const android::base::unique_fd& bugreport_fd_in,
Paul Changf59c2b72020-03-10 02:08:55 +08002887 const android::base::unique_fd& screenshot_fd_in,
2888 bool is_screenshot_requested) {
Kean Mariotti306633e2022-09-05 16:30:47 +00002889 this->use_predumped_ui_data = bugreport_flags & BugreportFlag::BUGREPORT_USE_PREDUMPED_UI_DATA;
Gavin Corkerya44686c2022-11-23 18:16:51 +00002890 this->is_consent_deferred = bugreport_flags & BugreportFlag::BUGREPORT_FLAG_DEFER_CONSENT;
Nandana Dutt54dbd672019-01-11 12:58:05 +00002891 // Duplicate the fds because the passed in fds don't outlive the binder transaction.
Todd Frederick621533f2022-03-26 02:54:17 +00002892 bugreport_fd.reset(fcntl(bugreport_fd_in.get(), F_DUPFD_CLOEXEC, 0));
2893 screenshot_fd.reset(fcntl(screenshot_fd_in.get(), F_DUPFD_CLOEXEC, 0));
Nandana Dutt58d72e22018-11-16 10:30:48 +00002894
Paul Changf59c2b72020-03-10 02:08:55 +08002895 SetOptionsFromMode(bugreport_mode, this, is_screenshot_requested);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002896}
2897
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002898Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
2899 RunStatus status = RunStatus::OK;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002900 int c;
mhasankd451a472020-05-26 18:02:39 -07002901 while ((c = getopt(argc, argv, "dho:svqzpLPBRSV:w")) != -1) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002902 switch (c) {
2903 // clang-format off
mhasank3a4cfb42020-06-15 18:06:43 -07002904 case 'o': out_dir = optarg; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002905 case 's': stream_to_socket = true; break;
2906 case 'S': progress_updates_to_socket = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002907 case 'v': show_header_only = true; break;
2908 case 'q': do_vibrate = false; break;
Paul Chang0d2aad72020-02-13 20:04:03 +08002909 case 'p': do_screenshot = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002910 case 'P': do_progress_updates = true; break;
2911 case 'R': is_remote_mode = true; break;
mhasankd451a472020-05-26 18:02:39 -07002912 case 'L': limited_only = true; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002913 case 'V':
2914 case 'd':
2915 case 'z':
2916 // compatibility no-op
2917 break;
Nandana Dutt235864b2019-01-22 12:10:16 +00002918 case 'w':
2919 // This was already processed
2920 break;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002921 case 'h':
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002922 status = RunStatus::HELP;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002923 break;
2924 default:
2925 fprintf(stderr, "Invalid option: %c\n", c);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002926 status = RunStatus::INVALID_INPUT;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002927 break;
2928 // clang-format on
2929 }
2930 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08002931
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002932 for (int i = 0; i < argc; i++) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002933 args += argv[i];
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002934 if (i < argc - 1) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002935 args += " ";
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002936 }
2937 }
2938
2939 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
2940 optind = 1;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002941
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002942 return status;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002943}
2944
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002945bool Dumpstate::DumpOptions::ValidateOptions() const {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002946 if (bugreport_fd.get() != -1 && stream_to_socket) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002947 return false;
2948 }
2949
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002950 if ((progress_updates_to_socket || do_progress_updates) && stream_to_socket) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002951 return false;
2952 }
2953
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002954 if (is_remote_mode && (do_progress_updates || stream_to_socket)) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002955 return false;
2956 }
2957 return true;
2958}
2959
Nandana Dutt197661d2018-11-16 16:40:21 +00002960void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
2961 options_ = std::move(options);
2962}
2963
Abhijeet Kaura407fb82020-03-27 12:51:12 +00002964void Dumpstate::Initialize() {
2965 /* gets the sequential id */
2966 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
2967 id_ = ++last_id;
2968 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
2969}
2970
Nandana Duttd2f5f082019-01-18 17:13:52 +00002971Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
2972 Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
Gavin Corkerya44686c2022-11-23 18:16:51 +00002973 HandleRunStatus(status);
2974 return status;
2975}
2976
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00002977Dumpstate::RunStatus Dumpstate::Retrieve(int32_t calling_uid, const std::string& calling_package,
2978 const bool keep_bugreport_on_retrieval) {
2979 Dumpstate::RunStatus status = RetrieveInternal(calling_uid, calling_package,
2980 keep_bugreport_on_retrieval);
Gavin Corkerya44686c2022-11-23 18:16:51 +00002981 HandleRunStatus(status);
2982 return status;
2983}
2984
2985Dumpstate::RunStatus Dumpstate::RetrieveInternal(int32_t calling_uid,
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00002986 const std::string& calling_package,
2987 const bool keep_bugreport_on_retrieval) {
Gavin Corkerya44686c2022-11-23 18:16:51 +00002988 consent_callback_ = new ConsentCallback();
2989 const String16 incidentcompanion("incidentcompanion");
2990 sp<android::IBinder> ics(
2991 defaultServiceManager()->checkService(incidentcompanion));
2992 android::String16 package(calling_package.c_str());
2993 if (ics != nullptr) {
2994 MYLOGD("Checking user consent via incidentcompanion service\n");
2995 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
2996 calling_uid, package, String16(), String16(),
2997 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
2998 } else {
2999 MYLOGD(
3000 "Unable to check user consent; incidentcompanion service unavailable\n");
3001 return RunStatus::USER_CONSENT_TIMED_OUT;
3002 }
3003 UserConsentResult consent_result = consent_callback_->getResult();
3004 int timeout_ms = 30 * 1000;
3005 while (consent_result == UserConsentResult::UNAVAILABLE &&
3006 consent_callback_->getElapsedTimeMs() < timeout_ms) {
3007 sleep(1);
3008 consent_result = consent_callback_->getResult();
3009 }
3010 if (consent_result == UserConsentResult::DENIED) {
3011 return RunStatus::USER_CONSENT_DENIED;
3012 }
3013 if (consent_result == UserConsentResult::UNAVAILABLE) {
3014 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3015 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3016 consent_callback_.get());
3017 return RunStatus::USER_CONSENT_TIMED_OUT;
3018 }
3019
3020 bool copy_succeeded =
3021 android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003022
3023 if (copy_succeeded && (!android::app::admin::flags::onboarding_bugreport_v2_enabled()
3024 || !keep_bugreport_on_retrieval)) {
3025 android::os::UnlinkAndLogOnError(path_);
Gavin Corkerya44686c2022-11-23 18:16:51 +00003026 }
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003027
Gavin Corkerya44686c2022-11-23 18:16:51 +00003028 return copy_succeeded ? Dumpstate::RunStatus::OK
3029 : Dumpstate::RunStatus::ERROR;
3030}
3031
3032void Dumpstate::HandleRunStatus(Dumpstate::RunStatus status) {
3033 if (listener_ != nullptr) {
Nandana Duttbabf6c72019-01-15 14:11:12 +00003034 switch (status) {
3035 case Dumpstate::RunStatus::OK:
Gavin Corkerya44686c2022-11-23 18:16:51 +00003036 listener_->onFinished(path_.c_str());
Nandana Duttbabf6c72019-01-15 14:11:12 +00003037 break;
3038 case Dumpstate::RunStatus::HELP:
3039 break;
3040 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003041 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00003042 break;
3043 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003044 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
3045 break;
3046 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3047 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
3048 break;
3049 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
3050 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00003051 break;
3052 }
3053 }
Nandana Duttbabf6c72019-01-15 14:11:12 +00003054}
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003055void Dumpstate::Cancel() {
3056 CleanupTmpFiles();
3057 android::os::UnlinkAndLogOnError(log_path_);
3058 for (int i = 0; i < NUM_OF_DUMPS; i++) {
3059 android::os::UnlinkAndLogOnError(ds.bugreport_internal_dir_ + "/" +
3060 kDumpstateBoardFiles[i]);
3061 }
3062 tombstone_data_.clear();
3063 anr_data_.clear();
Woody Lin20767a92022-11-29 15:50:24 +08003064 shutdown_checkpoints_.clear();
Rhed Jao0daac912020-08-21 14:48:20 +08003065
3066 // Instead of shutdown the pool, we delete temporary files directly since
3067 // shutdown blocking the call.
3068 if (dump_pool_) {
3069 dump_pool_->deleteTempFiles();
3070 }
3071 if (zip_entry_tasks_) {
3072 zip_entry_tasks_->run(/*do_cancel =*/ true);
3073 }
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003074}
3075
Kean Mariotti306633e2022-09-05 16:30:47 +00003076void Dumpstate::PreDumpUiData() {
Kean Mariotti853b73a2023-07-27 12:40:30 +00003077 MaybeSnapshotSystemTrace();
Kean Mariotti306633e2022-09-05 16:30:47 +00003078 MaybeSnapshotUiTraces();
3079}
3080
Nandana Dutt979388e2018-11-30 16:48:55 +00003081/*
3082 * Dumps relevant information to a bugreport based on the given options.
3083 *
3084 * The bugreport can be dumped to a file or streamed to a socket.
3085 *
3086 * How dumping to file works:
3087 * stdout is redirected to a temporary file. This will later become the main bugreport entry.
3088 * stderr is redirected a log file.
3089 *
3090 * The temporary bugreport is then populated via printfs, dumping contents of files and
3091 * output of commands to stdout.
3092 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003093 * A bunch of other files and dumps are added to the zip archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00003094 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003095 * The temporary bugreport file and the log file also get added to the archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00003096 *
mhasank2d75c442020-06-11 15:05:25 -07003097 * Bugreports are first generated in a local directory and later copied to the caller's fd
3098 * or directory if supplied.
Nandana Dutt979388e2018-11-30 16:48:55 +00003099 */
Nandana Duttd2f5f082019-01-18 17:13:52 +00003100Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
3101 const std::string& calling_package) {
Rhed Jao5377d792020-07-16 17:37:39 +08003102 DurationReporter duration_reporter("RUN INTERNAL", /* logcat_only = */true);
Nandana Dutt979388e2018-11-30 16:48:55 +00003103 LogDumpOptions(*options_);
Nandana Dutt197661d2018-11-16 16:40:21 +00003104 if (!options_->ValidateOptions()) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00003105 MYLOGE("Invalid options specified\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003106 return RunStatus::INVALID_INPUT;
3107 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003108 /* set as high priority, and protect from OOM killer */
3109 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003110
Felipe Lemed071c682016-10-20 16:48:00 -07003111 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07003112 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003113 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003114 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003115 } else {
3116 /* fallback to kernels <= 2.6.35 */
3117 oom_adj = fopen("/proc/self/oom_adj", "we");
3118 if (oom_adj) {
3119 fputs("-17", oom_adj);
3120 fclose(oom_adj);
3121 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003122 }
3123
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003124 if (version_ == VERSION_DEFAULT) {
3125 version_ = VERSION_CURRENT;
Michal Karpinski4db754f2015-12-11 18:04:32 +00003126 }
3127
Chris Morin5a50d482022-02-01 17:41:18 -08003128 if (version_ != VERSION_CURRENT) {
3129 MYLOGE("invalid version requested ('%s'); supported values are: ('%s', '%s')\n",
3130 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003131 return RunStatus::INVALID_INPUT;
Felipe Lemed071c682016-10-20 16:48:00 -07003132 }
3133
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003134 if (options_->show_header_only) {
3135 PrintHeader();
3136 return RunStatus::OK;
Felipe Lemed071c682016-10-20 16:48:00 -07003137 }
3138
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003139 MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n",
3140 calling_uid, calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003141
Felipe Leme7447d7c2016-11-03 18:12:22 -07003142 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003143 std::string stats_path =
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003144 android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003145 progress_.reset(new Progress(stats_path));
Felipe Leme7447d7c2016-11-03 18:12:22 -07003146
Sahana Raof35ed432019-07-12 10:47:52 +01003147 if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
3148 MYLOGE("Failed to acquire wake lock: %s\n", strerror(errno));
3149 } else {
3150 // Wake lock will be released automatically on process death
3151 MYLOGD("Wake lock acquired.\n");
3152 }
3153
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08003154 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07003155
Felipe Lemef0292972016-11-22 13:57:05 -08003156 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07003157 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
3158 }
3159
Kevin Jeonfa64e642023-07-27 11:36:41 -04003160 if (PropertiesHelper::IsStrictRun()) {
3161 MYLOGI(
3162 "Running on strict-run mode, which has shorter timeouts "
3163 "(to disable, call 'setprop dumpstate.strict_run false')\n");
3164 }
3165
Nandana Dutt235c6672019-11-14 15:22:32 +00003166 MYLOGI("dumpstate info: id=%d, args='%s', bugreport_mode= %s bugreport format version: %s\n",
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00003167 id_, options_->args.c_str(), options_->bugreport_mode_string.c_str(), version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08003168
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003169 do_early_screenshot_ = options_->do_progress_updates;
Felipe Lemee338bf62015-12-07 14:03:50 -08003170
Christopher Ferrised9354f2014-10-01 17:35:01 -07003171 // If we are going to use a socket, do it as early as possible
3172 // to avoid timeouts from bugreport.
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003173 if (options_->stream_to_socket || options_->progress_updates_to_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07003174 MYLOGD("Opening control socket\n");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003175 control_socket_fd_ = open_socket_fn_("dumpstate");
Nandana Dutta344cb62019-02-22 15:12:35 +00003176 if (control_socket_fd_ == -1) {
3177 return ERROR;
3178 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003179 if (options_->progress_updates_to_socket) {
3180 options_->do_progress_updates = 1;
3181 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07003182 }
3183
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003184 if (!PrepareToWriteToFile()) {
3185 return ERROR;
3186 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08003187
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003188 // Interactive, wear & telephony modes are default to true.
3189 // and may enable from cli option or when using control socket
3190 if (options_->do_progress_updates) {
3191 // clang-format off
3192 std::vector<std::string> am_args = {
3193 "--receiver-permission", "android.permission.DUMP",
3194 };
3195 // clang-format on
3196 // Send STARTED broadcast for apps that listen to bugreport generation events
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003197 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED",
3198 am_args, multiuser_get_user_id(calling_uid));
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003199 if (options_->progress_updates_to_socket) {
3200 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08003201 }
3202 }
3203
Nick Kralevichf3599b32016-01-25 15:05:16 -08003204 /* read /proc/cmdline before dropping root */
3205 FILE *cmdline = fopen("/proc/cmdline", "re");
3206 if (cmdline) {
3207 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
3208 fclose(cmdline);
3209 }
3210
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003211 if (options_->do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08003212 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05003213 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003214
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003215 if (zip_file != nullptr) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003216 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
3217 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003218 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08003219 }
3220 }
3221
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003222 int dup_stdout_fd;
3223 int dup_stderr_fd;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003224 // Redirect stderr to log_path_ for debugging.
3225 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
3226 if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
3227 return ERROR;
3228 }
3229 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
3230 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
3231 strerror(errno));
3232 }
Nandana Dutt979388e2018-11-30 16:48:55 +00003233
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003234 // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
3235 // moved into zip file later, if zipping.
3236 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
3237 // TODO: why not write to a file instead of stdout to overcome this problem?
3238 /* TODO: rather than generating a text file now and zipping it later,
3239 it would be more efficient to redirect stdout to the zip entry
3240 directly, but the libziparchive doesn't support that option yet. */
3241 if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
3242 return ERROR;
3243 }
3244 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
3245 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
3246 tmp_path_.c_str(), strerror(errno));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003247 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08003248
3249 // Don't buffer stdout
3250 setvbuf(stdout, nullptr, _IONBF, 0);
3251
Rhed Jao5377d792020-07-16 17:37:39 +08003252 // Enable the parallel run if the client requests to output to a file.
3253 EnableParallelRunIfNeeded();
3254 // Using scope guard to make sure the dump pool can be shut down correctly.
3255 auto scope_guard_to_shutdown_pool = android::base::make_scope_guard([=]() {
3256 ShutdownDumpPool();
3257 });
3258
Felipe Leme608385d2016-02-01 10:35:38 -08003259 // NOTE: there should be no stdout output until now, otherwise it would break the header.
3260 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08003261 // duration is logged into MYLOG instead.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003262 PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003263
Kean Mariotti853b73a2023-07-27 12:40:30 +00003264 bool is_dumpstate_restricted =
3265 options_->telephony_only || options_->wifi_only || options_->limited_only;
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003266 if (!is_dumpstate_restricted) {
3267 // Snapshot the system trace now (if running) to avoid that dumpstate's
3268 // own activity pushes out interesting data from the trace ring buffer.
3269 // The trace file is added to the zip by MaybeAddSystemTraceToZip().
3270 MaybeSnapshotSystemTrace();
Yohei Yukawa95305b32021-03-09 07:54:27 -08003271
Kean Mariotti853b73a2023-07-27 12:40:30 +00003272 // Invoke critical dumpsys to preserve system state, before doing anything else.
3273 RunDumpsysCritical();
3274
Kean Mariotti306633e2022-09-05 16:30:47 +00003275 // Snapshot the UI traces now (if running).
3276 // The trace files will be added to bugreport later.
3277 MaybeSnapshotUiTraces();
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003278 }
Kean Mariotti853b73a2023-07-27 12:40:30 +00003279
3280 MaybeTakeEarlyScreenshot();
Gavin Corkery6968f552020-11-22 18:09:05 +00003281 onUiIntensiveBugreportDumpsFinished(calling_uid);
3282 MaybeCheckUserConsent(calling_uid, calling_package);
3283 if (options_->telephony_only) {
3284 DumpstateTelephonyOnly(calling_package);
3285 } else if (options_->wifi_only) {
3286 DumpstateWifiOnly();
3287 } else if (options_->limited_only) {
3288 DumpstateLimitedOnly();
Elis Elliott8e401ad2023-08-08 11:18:59 +00003289 } else if (options_->onboarding_only) {
3290 DumpstateOnboardingOnly();
Gavin Corkery6968f552020-11-22 18:09:05 +00003291 } else {
Nandana Dutt4be45d12018-09-26 15:04:23 +01003292 // Dump state for the default case. This also drops root.
Jichao Lie89d9c12019-11-21 19:02:51 -08003293 RunStatus s = DumpstateDefaultAfterCritical();
Nandana Dutt5c390032019-03-12 10:52:56 +00003294 if (s != RunStatus::OK) {
Nandana Duttaac6f582019-07-26 14:32:47 +01003295 if (s == RunStatus::USER_CONSENT_DENIED) {
Nandana Dutt5c390032019-03-12 10:52:56 +00003296 HandleUserConsentDenied();
3297 }
3298 return s;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08003299 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07003300 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07003301
Felipe Leme55b42a62015-11-10 17:39:08 -08003302 /* close output if needed */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003303 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003304
Abhijeet Kaure370d682019-10-01 16:49:30 +01003305 // Zip the (now complete) .tmp file within the internal directory.
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003306 ATRACE_BEGIN("FinalizeFile");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003307 FinalizeFile();
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003308 ATRACE_END();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003309
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003310 // Share the final file with the caller if the user has consented or Shell is the caller.
Nandana Duttd2f5f082019-01-18 17:13:52 +00003311 Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
Gavin Corkerya44686c2022-11-23 18:16:51 +00003312 if (CalledByApi() && !options_->is_consent_deferred) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003313 status = CopyBugreportIfUserConsented(calling_uid);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003314 if (status != Dumpstate::RunStatus::OK &&
3315 status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3316 // Do an early return if there were errors. We make an exception for consent
3317 // timing out because it's possible the user got distracted. In this case the
3318 // bugreport is not shared but made available for manual retrieval.
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003319 MYLOGI("User denied consent. Returning\n");
Nandana Duttd2f5f082019-01-18 17:13:52 +00003320 return status;
3321 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003322 if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3323 MYLOGI(
3324 "Did not receive user consent yet."
3325 " Will not copy the bugreport artifacts to caller.\n");
Abhijeet Kaur57627412019-04-17 16:00:09 +01003326 const String16 incidentcompanion("incidentcompanion");
3327 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
3328 if (ics != nullptr) {
3329 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3330 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3331 consent_callback_.get());
3332 } else {
3333 MYLOGD("Unable to cancel user consent; incidentcompanion service unavailable\n");
3334 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003335 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003336 }
3337
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003338 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003339 if (options_->do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09003340 for (int i = 0; i < 3; i++) {
3341 Vibrate(75);
3342 usleep((75 + 50) * 1000);
3343 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003344 }
3345
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003346 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
3347 progress_->GetInitialMax());
3348 progress_->Save();
3349 MYLOGI("done (id %d)\n", id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003350
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003351 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08003352
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003353 if (control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07003354 MYLOGD("Closing control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003355 close(control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07003356 }
3357
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003358 tombstone_data_.clear();
3359 anr_data_.clear();
Woody Lin20767a92022-11-29 15:50:24 +08003360 shutdown_checkpoints_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01003361
Nandana Duttd2f5f082019-01-18 17:13:52 +00003362 return (consent_callback_ != nullptr &&
3363 consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
3364 ? USER_CONSENT_TIMED_OUT
3365 : RunStatus::OK;
3366}
3367
Paul Chang0d2aad72020-02-13 20:04:03 +08003368void Dumpstate::MaybeTakeEarlyScreenshot() {
3369 if (!options_->do_screenshot || !do_early_screenshot_) {
3370 return;
3371 }
3372
3373 TakeScreenshot();
3374}
3375
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003376void Dumpstate::MaybeSnapshotSystemTrace() {
Kean Mariotti853b73a2023-07-27 12:40:30 +00003377 // When capturing traces via bugreport handler (BH), this function will be invoked twice:
3378 // 1) When BH invokes IDumpstate::PreDumpUiData()
3379 // 2) When BH invokes IDumpstate::startBugreport(flags = BUGREPORT_USE_PREDUMPED_UI_DATA)
3380 // In this case we don't want to re-invoke perfetto in step 2.
3381 // In all other standard invocation states, this function is invoked once
3382 // without the flag BUGREPORT_USE_PREDUMPED_UI_DATA.
3383 if (options_->use_predumped_ui_data) {
3384 return;
3385 }
3386
3387 // If a stale file exists already, remove it.
3388 unlink(SYSTEM_TRACE_SNAPSHOT);
3389
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003390 // If a background system trace is happening and is marked as "suitable for
3391 // bugreport" (i.e. bugreport_score > 0 in the trace config), this command
3392 // will stop it and serialize into SYSTEM_TRACE_SNAPSHOT. In the (likely)
3393 // case that no trace is ongoing, this command is a no-op.
3394 // Note: this should not be enqueued as we need to freeze the trace before
3395 // dumpstate starts. Otherwise the trace ring buffers will contain mostly
3396 // the dumpstate's own activity which is irrelevant.
Kean Mariotti853b73a2023-07-27 12:40:30 +00003397 RunCommand("SERIALIZE PERFETTO TRACE", {"perfetto", "--save-for-bugreport"},
3398 CommandOptions::WithTimeout(10).DropRoot().CloseAllFileDescriptorsOnExec().Build());
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003399 // MaybeAddSystemTraceToZip() will take care of copying the trace in the zip
3400 // file in the later stages.
3401}
3402
Kean Mariotti306633e2022-09-05 16:30:47 +00003403void Dumpstate::MaybeSnapshotUiTraces() {
3404 if (PropertiesHelper::IsUserBuild() || options_->use_predumped_ui_data) {
3405 return;
3406 }
3407
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003408 const std::vector<std::vector<std::string>> dumpTracesForBugReportCommands = {
3409 {"dumpsys", "activity", "service", "SystemUIService", "WMShell", "protolog",
3410 "save-for-bugreport"},
3411 {"dumpsys", "activity", "service", "SystemUIService", "WMShell", "transitions", "tracing",
3412 "save-for-bugreport"},
3413 {"cmd", "input_method", "tracing", "save-for-bugreport"},
3414 {"cmd", "window", "tracing", "save-for-bugreport"},
3415 {"cmd", "window", "shell", "tracing", "save-for-bugreport"},
3416 };
Hongwei Wang39229132023-01-24 15:09:59 -08003417
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003418 for (const auto& command : dumpTracesForBugReportCommands) {
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003419 RunCommand(
3420 // Empty name because it's not intended to be classified as a bugreport section.
3421 // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003422 "", command,
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003423 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
3424 }
Kean Mariotti306633e2022-09-05 16:30:47 +00003425}
3426
3427void Dumpstate::MaybeAddUiTracesToZip() {
3428 if (PropertiesHelper::IsUserBuild()) {
3429 return;
3430 }
3431
3432 ds.AddDir(WMTRACE_DATA_DIR, false);
Yohei Yukawa95305b32021-03-09 07:54:27 -08003433}
3434
Paul Changeb4b4642020-05-28 22:05:47 +08003435void Dumpstate::onUiIntensiveBugreportDumpsFinished(int32_t calling_uid) {
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003436 if (multiuser_get_app_id(calling_uid) == AID_SHELL || !CalledByApi()) {
Paul Changc490e662020-04-11 18:14:09 +08003437 return;
3438 }
3439 if (listener_ != nullptr) {
3440 // Let listener know ui intensive bugreport dumps are finished, then it can do event
3441 // handling if required.
Paul Changeb4b4642020-05-28 22:05:47 +08003442 listener_->onUiIntensiveBugreportDumpsFinished();
Paul Changc490e662020-04-11 18:14:09 +08003443 }
3444}
3445
Jichao Lie89d9c12019-11-21 19:02:51 -08003446void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) {
Gavin Corkerya44686c2022-11-23 18:16:51 +00003447 if (multiuser_get_app_id(calling_uid) == AID_SHELL ||
3448 !CalledByApi() || options_->is_consent_deferred) {
3449 // No need to get consent for shell triggered dumpstates, or not
3450 // through bugreporting API (i.e. no fd to copy back), or when consent
3451 // is deferred.
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003452 return;
3453 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003454 consent_callback_ = new ConsentCallback();
3455 const String16 incidentcompanion("incidentcompanion");
3456 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
Jichao Lie89d9c12019-11-21 19:02:51 -08003457 android::String16 package(calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003458 if (ics != nullptr) {
3459 MYLOGD("Checking user consent via incidentcompanion service\n");
Steven Leeb573eb82022-11-29 22:31:35 +08003460 int flags = 0x1; // IncidentManager.FLAG_CONFIRMATION_DIALOG
3461 if (IsConsentlessBugreportAllowed(*options_)) {
3462 flags |= 0x2; // IncidentManager.FLAG_ALLOW_CONSENTLESS_BUGREPORT
3463 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003464 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
Steven Leeb573eb82022-11-29 22:31:35 +08003465 calling_uid, package, String16(), String16(), flags, consent_callback_.get());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003466 } else {
3467 MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
3468 }
3469}
3470
Nandana Dutt5c390032019-03-12 10:52:56 +00003471bool Dumpstate::IsUserConsentDenied() const {
3472 return ds.consent_callback_ != nullptr &&
3473 ds.consent_callback_->getResult() == UserConsentResult::DENIED;
3474}
3475
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01003476bool Dumpstate::CalledByApi() const {
3477 return ds.options_->bugreport_fd.get() != -1 ? true : false;
3478}
3479
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003480void Dumpstate::CleanupTmpFiles() {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003481 android::os::UnlinkAndLogOnError(tmp_path_);
3482 android::os::UnlinkAndLogOnError(screenshot_path_);
3483 android::os::UnlinkAndLogOnError(path_);
Gavin Corkery789d7a52021-02-24 23:52:35 +00003484 if (dump_traces_path != nullptr) {
3485 android::os::UnlinkAndLogOnError(dump_traces_path);
3486 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003487}
3488
Rhed Jao5377d792020-07-16 17:37:39 +08003489void Dumpstate::EnableParallelRunIfNeeded() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003490 if (!PropertiesHelper::IsParallelRun()) {
Rhed Jao5377d792020-07-16 17:37:39 +08003491 return;
3492 }
3493 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003494 zip_entry_tasks_ = std::make_unique<TaskQueue>();
Rhed Jao5377d792020-07-16 17:37:39 +08003495}
3496
3497void Dumpstate::ShutdownDumpPool() {
3498 if (dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08003499 dump_pool_.reset();
Rhed Jao5377d792020-07-16 17:37:39 +08003500 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003501 if (zip_entry_tasks_) {
3502 zip_entry_tasks_->run(/* do_cancel = */true);
3503 zip_entry_tasks_ = nullptr;
3504 }
3505}
3506
3507void Dumpstate::EnqueueAddZipEntryAndCleanupIfNeeded(const std::string& entry_name,
3508 const std::string& entry_path) {
3509 auto func_add_zip_entry_and_cleanup = [=](bool task_cancelled) {
3510 if (!task_cancelled) {
3511 AddZipEntry(entry_name, entry_path);
3512 }
3513 android::os::UnlinkAndLogOnError(entry_path);
3514 };
3515 if (zip_entry_tasks_) {
3516 // Enqueues AddZipEntryAndCleanup function if the parallel run is enabled.
3517 zip_entry_tasks_->add(func_add_zip_entry_and_cleanup, _1);
3518 } else {
3519 // Invokes AddZipEntryAndCleanup immediately
3520 std::invoke(func_add_zip_entry_and_cleanup, /* task_cancelled = */false);
3521 }
Rhed Jao5377d792020-07-16 17:37:39 +08003522}
3523
Nandana Duttd2f5f082019-01-18 17:13:52 +00003524Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
3525 MYLOGD("User denied consent; deleting files and returning\n");
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003526 CleanupTmpFiles();
Nandana Duttd2f5f082019-01-18 17:13:52 +00003527 return USER_CONSENT_DENIED;
3528}
3529
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003530Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented(int32_t calling_uid) {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003531 // If the caller has asked to copy the bugreport over to their directory, we need explicit
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003532 // user consent (unless the caller is Shell).
3533 UserConsentResult consent_result;
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003534 if (multiuser_get_app_id(calling_uid) == AID_SHELL) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003535 consent_result = UserConsentResult::APPROVED;
3536 } else {
3537 consent_result = consent_callback_->getResult();
3538 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003539 if (consent_result == UserConsentResult::UNAVAILABLE) {
3540 // User has not responded yet.
3541 uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
Hunter Knepshield70610fa2020-01-03 15:27:33 -08003542 // Telephony is a fast report type, particularly on user builds where information may be
3543 // more aggressively limited. To give the user time to read the consent dialog, increase the
3544 // timeout.
3545 uint64_t timeout_ms = options_->telephony_only ? TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS
3546 : USER_CONSENT_TIMEOUT_MS;
3547 if (elapsed_ms < timeout_ms) {
3548 uint delay_seconds = (timeout_ms - elapsed_ms) / 1000;
Nandana Duttd2f5f082019-01-18 17:13:52 +00003549 MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
3550 sleep(delay_seconds);
3551 }
3552 consent_result = consent_callback_->getResult();
3553 }
3554 if (consent_result == UserConsentResult::DENIED) {
3555 // User has explicitly denied sharing with the app. To be safe delete the
3556 // internal bugreport & tmp files.
3557 return HandleUserConsentDenied();
3558 }
3559 if (consent_result == UserConsentResult::APPROVED) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00003560 bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
3561 if (copy_succeeded) {
3562 android::os::UnlinkAndLogOnError(path_);
Abhijeet Kaur9ce94672020-04-01 17:22:36 +01003563 if (options_->do_screenshot &&
3564 options_->screenshot_fd.get() != -1 &&
3565 !options_->is_screenshot_copied) {
3566 copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
3567 options_->screenshot_fd.get());
3568 options_->is_screenshot_copied = copy_succeeded;
3569 if (copy_succeeded) {
3570 android::os::UnlinkAndLogOnError(screenshot_path_);
3571 }
3572 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003573 }
3574 return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
3575 } else if (consent_result == UserConsentResult::UNAVAILABLE) {
3576 // consent_result is still UNAVAILABLE. The user has likely not responded yet.
3577 // Since we do not have user consent to share the bugreport it does not get
3578 // copied over to the calling app but remains in the internal directory from
3579 // where the user can manually pull it.
Paul Changce644212021-05-11 16:06:45 +08003580 std::string final_path = GetPath(".zip");
3581 bool copy_succeeded = android::os::CopyFileToFile(path_, final_path);
3582 if (copy_succeeded) {
3583 android::os::UnlinkAndLogOnError(path_);
3584 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003585 return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
3586 }
3587 // Unknown result; must be a programming error.
3588 MYLOGE("Unknown user consent result:%d\n", consent_result);
3589 return Dumpstate::RunStatus::ERROR;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003590}
3591
Nandana Duttf02564e2019-02-15 15:24:24 +00003592Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003593 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
3594 Dumpstate::RunStatus status = options->Initialize(argc, argv);
3595 if (status == Dumpstate::RunStatus::OK) {
Nandana Duttf02564e2019-02-15 15:24:24 +00003596 SetOptions(std::move(options));
Nandana Duttd2f5f082019-01-18 17:13:52 +00003597 // When directly running dumpstate binary, the output is not expected to be written
3598 // to any external file descriptor.
Nandana Duttf02564e2019-02-15 15:24:24 +00003599 assert(options_->bugreport_fd.get() == -1);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003600
3601 // calling_uid and calling_package are for user consent to share the bugreport with
Abhijeet Kaura407fb82020-03-27 12:51:12 +00003602 // an app; they are irrelevant here because bugreport is triggered via command line.
3603 // Update Last ID before calling Run().
3604 Initialize();
Nikhil Kumarb70622a2023-06-15 15:37:19 +01003605 status = Run(0 /* calling_uid */, "" /* calling_package */);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003606 }
Nandana Duttf02564e2019-02-15 15:24:24 +00003607 return status;
3608}
3609
3610/* Main entry point for dumpstate binary. */
3611int run_main(int argc, char* argv[]) {
3612 Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003613
3614 switch (status) {
3615 case Dumpstate::RunStatus::OK:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003616 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003617 case Dumpstate::RunStatus::HELP:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003618 ShowUsage();
3619 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003620 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003621 fprintf(stderr, "Invalid combination of args\n");
3622 ShowUsage();
3623 exit(1);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003624 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003625 FALLTHROUGH_INTENDED;
3626 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3627 FALLTHROUGH_INTENDED;
3628 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003629 exit(2);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003630 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003631}
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003632
3633// TODO(111441001): Default DumpOptions to sensible values.
3634Dumpstate::Dumpstate(const std::string& version)
3635 : pid_(getpid()),
3636 options_(new Dumpstate::DumpOptions()),
Nandana Dutt402a8392019-06-14 14:25:13 +01003637 last_reported_percent_progress_(0),
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003638 version_(version),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003639 now_(time(nullptr)),
3640 open_socket_fn_(open_socket) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003641}
3642
3643Dumpstate& Dumpstate::GetInstance() {
3644 static Dumpstate singleton_(android::base::GetProperty("dumpstate.version", VERSION_CURRENT));
3645 return singleton_;
3646}
3647
Rhed Jao5377d792020-07-16 17:37:39 +08003648DurationReporter::DurationReporter(const std::string& title, bool logcat_only, bool verbose,
3649 int duration_fd) : title_(title), logcat_only_(logcat_only), verbose_(verbose),
3650 duration_fd_(duration_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003651 if (!title_.empty()) {
3652 started_ = Nanotime();
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003653 if (title_.find("SHOW MAP") == std::string::npos) {
3654 ATRACE_ASYNC_BEGIN(title_.c_str(), 0);
3655 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003656 }
3657}
3658
3659DurationReporter::~DurationReporter() {
3660 if (!title_.empty()) {
3661 float elapsed = (float)(Nanotime() - started_) / NANOS_PER_SEC;
chenqiwuaf8b2d92019-12-12 18:53:51 +08003662 if (elapsed >= .5f || verbose_) {
3663 MYLOGD("Duration of '%s': %.2fs\n", title_.c_str(), elapsed);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003664 }
chenqiwuaf8b2d92019-12-12 18:53:51 +08003665 if (!logcat_only_) {
3666 // Use "Yoda grammar" to make it easier to grep|sort sections.
Rhed Jao5377d792020-07-16 17:37:39 +08003667 dprintf(duration_fd_, "------ %.3fs was the duration of '%s' ------\n",
3668 elapsed, title_.c_str());
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003669 }
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003670 if (title_.find("SHOW MAP") == std::string::npos) {
3671 ATRACE_ASYNC_END(title_.c_str(), 0);
3672 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003673 }
3674}
3675
3676const int32_t Progress::kDefaultMax = 5000;
3677
3678Progress::Progress(const std::string& path) : Progress(Progress::kDefaultMax, 1.1, path) {
3679}
3680
3681Progress::Progress(int32_t initial_max, int32_t progress, float growth_factor)
3682 : Progress(initial_max, growth_factor, "") {
3683 progress_ = progress;
3684}
3685
3686Progress::Progress(int32_t initial_max, float growth_factor, const std::string& path)
3687 : initial_max_(initial_max),
3688 progress_(0),
3689 max_(initial_max),
3690 growth_factor_(growth_factor),
3691 n_runs_(0),
3692 average_max_(0),
3693 path_(path) {
3694 if (!path_.empty()) {
3695 Load();
3696 }
3697}
3698
3699void Progress::Load() {
3700 MYLOGD("Loading stats from %s\n", path_.c_str());
3701 std::string content;
3702 if (!android::base::ReadFileToString(path_, &content)) {
3703 MYLOGI("Could not read stats from %s; using max of %d\n", path_.c_str(), max_);
3704 return;
3705 }
3706 if (content.empty()) {
3707 MYLOGE("No stats (empty file) on %s; using max of %d\n", path_.c_str(), max_);
3708 return;
3709 }
3710 std::vector<std::string> lines = android::base::Split(content, "\n");
3711
3712 if (lines.size() < 1) {
3713 MYLOGE("Invalid stats on file %s: not enough lines (%d). Using max of %d\n", path_.c_str(),
3714 (int)lines.size(), max_);
3715 return;
3716 }
3717 char* ptr;
3718 n_runs_ = strtol(lines[0].c_str(), &ptr, 10);
3719 average_max_ = strtol(ptr, nullptr, 10);
3720 if (n_runs_ <= 0 || average_max_ <= 0 || n_runs_ > STATS_MAX_N_RUNS ||
3721 average_max_ > STATS_MAX_AVERAGE) {
3722 MYLOGE("Invalid stats line on file %s: %s\n", path_.c_str(), lines[0].c_str());
3723 initial_max_ = Progress::kDefaultMax;
3724 } else {
3725 initial_max_ = average_max_;
3726 }
3727 max_ = initial_max_;
3728
3729 MYLOGI("Average max progress: %d in %d runs; estimated max: %d\n", average_max_, n_runs_, max_);
3730}
3731
3732void Progress::Save() {
3733 int32_t total = n_runs_ * average_max_ + progress_;
3734 int32_t runs = n_runs_ + 1;
3735 int32_t average = floor(((float)total) / runs);
3736 MYLOGI("Saving stats (total=%d, runs=%d, average=%d) on %s\n", total, runs, average,
3737 path_.c_str());
3738 if (path_.empty()) {
3739 return;
3740 }
3741
3742 std::string content = android::base::StringPrintf("%d %d\n", runs, average);
3743 if (!android::base::WriteStringToFile(content, path_)) {
3744 MYLOGE("Could not save stats on %s\n", path_.c_str());
3745 }
3746}
3747
3748int32_t Progress::Get() const {
3749 return progress_;
3750}
3751
3752bool Progress::Inc(int32_t delta_sec) {
3753 bool changed = false;
3754 if (delta_sec >= 0) {
3755 progress_ += delta_sec;
3756 if (progress_ > max_) {
3757 int32_t old_max = max_;
3758 max_ = floor((float)progress_ * growth_factor_);
3759 MYLOGD("Adjusting max progress from %d to %d\n", old_max, max_);
3760 changed = true;
3761 }
3762 }
3763 return changed;
3764}
3765
3766int32_t Progress::GetMax() const {
3767 return max_;
3768}
3769
3770int32_t Progress::GetInitialMax() const {
3771 return initial_max_;
3772}
3773
3774void Progress::Dump(int fd, const std::string& prefix) const {
3775 const char* pr = prefix.c_str();
3776 dprintf(fd, "%sprogress: %d\n", pr, progress_);
3777 dprintf(fd, "%smax: %d\n", pr, max_);
3778 dprintf(fd, "%sinitial_max: %d\n", pr, initial_max_);
3779 dprintf(fd, "%sgrowth_factor: %0.2f\n", pr, growth_factor_);
3780 dprintf(fd, "%spath: %s\n", pr, path_.c_str());
3781 dprintf(fd, "%sn_runs: %d\n", pr, n_runs_);
3782 dprintf(fd, "%saverage_max: %d\n", pr, average_max_);
3783}
3784
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003785std::string Dumpstate::GetPath(const std::string& suffix) const {
3786 return GetPath(bugreport_internal_dir_, suffix);
3787}
3788
3789std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
3790 return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
3791 name_.c_str(), suffix.c_str());
3792}
3793
3794void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
3795 progress_ = std::move(progress);
3796}
3797
3798void for_each_userid(void (*func)(int), const char *header) {
3799 std::string title = header == nullptr ? "for_each_userid" : android::base::StringPrintf(
3800 "for_each_userid(%s)", header);
3801 DurationReporter duration_reporter(title);
3802 if (PropertiesHelper::IsDryRun()) return;
3803
3804 DIR *d;
3805 struct dirent *de;
3806
3807 if (header) printf("\n------ %s ------\n", header);
3808 func(0);
3809
3810 if (!(d = opendir("/data/system/users"))) {
3811 printf("Failed to open /data/system/users (%s)\n", strerror(errno));
3812 return;
3813 }
3814
3815 while ((de = readdir(d))) {
3816 int userid;
3817 if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
3818 continue;
3819 }
3820 func(userid);
3821 }
3822
3823 closedir(d);
3824}
3825
3826static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
3827 DIR *d;
3828 struct dirent *de;
3829
3830 if (!(d = opendir("/proc"))) {
3831 printf("Failed to open /proc (%s)\n", strerror(errno));
3832 return;
3833 }
3834
3835 if (header) printf("\n------ %s ------\n", header);
3836 while ((de = readdir(d))) {
3837 if (ds.IsUserConsentDenied()) {
3838 MYLOGE(
3839 "Returning early because user denied consent to share bugreport with calling app.");
3840 closedir(d);
3841 return;
3842 }
3843 int pid;
3844 int fd;
3845 char cmdpath[255];
3846 char cmdline[255];
3847
3848 if (!(pid = atoi(de->d_name))) {
3849 continue;
3850 }
3851
3852 memset(cmdline, 0, sizeof(cmdline));
3853
3854 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
3855 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3856 TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
3857 close(fd);
3858 if (cmdline[0]) {
3859 helper(pid, cmdline, arg);
3860 continue;
3861 }
3862 }
3863
3864 // if no cmdline, a kernel thread has comm
3865 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
3866 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3867 TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
3868 close(fd);
3869 if (cmdline[1]) {
3870 cmdline[0] = '[';
3871 size_t len = strcspn(cmdline, "\f\b\r\n");
3872 cmdline[len] = ']';
3873 cmdline[len+1] = '\0';
3874 }
3875 }
3876 if (!cmdline[0]) {
3877 strcpy(cmdline, "N/A");
3878 }
3879 helper(pid, cmdline, arg);
3880 }
3881
3882 closedir(d);
3883}
3884
3885static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
3886 for_each_pid_func *func = (for_each_pid_func*) arg;
3887 func(pid, cmdline);
3888}
3889
3890void for_each_pid(for_each_pid_func func, const char *header) {
3891 std::string title = header == nullptr ? "for_each_pid"
3892 : android::base::StringPrintf("for_each_pid(%s)", header);
3893 DurationReporter duration_reporter(title);
3894 if (PropertiesHelper::IsDryRun()) return;
3895
3896 __for_each_pid(for_each_pid_helper, header, (void *) func);
3897}
3898
3899static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
3900 DIR *d;
3901 struct dirent *de;
3902 char taskpath[255];
3903 for_each_tid_func *func = (for_each_tid_func *) arg;
3904
3905 snprintf(taskpath, sizeof(taskpath), "/proc/%d/task", pid);
3906
3907 if (!(d = opendir(taskpath))) {
3908 printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
3909 return;
3910 }
3911
3912 func(pid, pid, cmdline);
3913
3914 while ((de = readdir(d))) {
3915 if (ds.IsUserConsentDenied()) {
3916 MYLOGE(
3917 "Returning early because user denied consent to share bugreport with calling app.");
3918 closedir(d);
3919 return;
3920 }
3921 int tid;
3922 int fd;
3923 char commpath[255];
3924 char comm[255];
3925
3926 if (!(tid = atoi(de->d_name))) {
3927 continue;
3928 }
3929
3930 if (tid == pid)
3931 continue;
3932
3933 snprintf(commpath, sizeof(commpath), "/proc/%d/comm", tid);
3934 memset(comm, 0, sizeof(comm));
3935 if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
3936 strcpy(comm, "N/A");
3937 } else {
3938 char *c;
3939 TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
3940 close(fd);
3941
3942 c = strrchr(comm, '\n');
3943 if (c) {
3944 *c = '\0';
3945 }
3946 }
3947 func(pid, tid, comm);
3948 }
3949
3950 closedir(d);
3951}
3952
3953void for_each_tid(for_each_tid_func func, const char *header) {
3954 std::string title = header == nullptr ? "for_each_tid"
3955 : android::base::StringPrintf("for_each_tid(%s)", header);
3956 DurationReporter duration_reporter(title);
3957
3958 if (PropertiesHelper::IsDryRun()) return;
3959
3960 __for_each_pid(for_each_tid_helper, header, (void *) func);
3961}
3962
3963void show_wchan(int pid, int tid, const char *name) {
3964 if (PropertiesHelper::IsDryRun()) return;
3965
3966 char path[255];
3967 char buffer[255];
3968 int fd, ret, save_errno;
3969 char name_buffer[255];
3970
3971 memset(buffer, 0, sizeof(buffer));
3972
3973 snprintf(path, sizeof(path), "/proc/%d/wchan", tid);
3974 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
3975 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
3976 return;
3977 }
3978
3979 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3980 save_errno = errno;
3981 close(fd);
3982
3983 if (ret < 0) {
3984 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
3985 return;
3986 }
3987
3988 snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
3989 pid == tid ? 0 : 3, "", name);
3990
3991 printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
3992
3993 return;
3994}
3995
3996// print time in centiseconds
3997static void snprcent(char *buffer, size_t len, size_t spc,
3998 unsigned long long time) {
3999 static long hz; // cache discovered hz
4000
4001 if (hz <= 0) {
4002 hz = sysconf(_SC_CLK_TCK);
4003 if (hz <= 0) {
4004 hz = 1000;
4005 }
4006 }
4007
4008 // convert to centiseconds
4009 time = (time * 100 + (hz / 2)) / hz;
4010
4011 char str[16];
4012
4013 snprintf(str, sizeof(str), " %llu.%02u",
4014 time / 100, (unsigned)(time % 100));
4015 size_t offset = strlen(buffer);
4016 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
4017 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
4018}
4019
4020// print permille as a percent
4021static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
4022 char str[16];
4023
4024 snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
4025 size_t offset = strlen(buffer);
4026 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
4027 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
4028}
4029
4030void show_showtime(int pid, const char *name) {
4031 if (PropertiesHelper::IsDryRun()) return;
4032
4033 char path[255];
4034 char buffer[1023];
4035 int fd, ret, save_errno;
4036
4037 memset(buffer, 0, sizeof(buffer));
4038
4039 snprintf(path, sizeof(path), "/proc/%d/stat", pid);
4040 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
4041 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
4042 return;
4043 }
4044
4045 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
4046 save_errno = errno;
4047 close(fd);
4048
4049 if (ret < 0) {
4050 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
4051 return;
4052 }
4053
4054 // field 14 is utime
4055 // field 15 is stime
4056 // field 42 is iotime
4057 unsigned long long utime = 0, stime = 0, iotime = 0;
4058 if (sscanf(buffer,
4059 "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
4060 "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
4061 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
4062 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
4063 &utime, &stime, &iotime) != 3) {
4064 return;
4065 }
4066
4067 unsigned long long total = utime + stime;
4068 if (!total) {
4069 return;
4070 }
4071
4072 unsigned permille = (iotime * 1000 + (total / 2)) / total;
4073 if (permille > 1000) {
4074 permille = 1000;
4075 }
4076
4077 // try to beautify and stabilize columns at <80 characters
4078 snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
4079 if ((name[0] != '[') || utime) {
4080 snprcent(buffer, sizeof(buffer), 57, utime);
4081 }
4082 snprcent(buffer, sizeof(buffer), 65, stime);
4083 if ((name[0] != '[') || iotime) {
4084 snprcent(buffer, sizeof(buffer), 73, iotime);
4085 }
4086 if (iotime) {
4087 snprdec(buffer, sizeof(buffer), 79, permille);
4088 }
4089 puts(buffer); // adds a trailing newline
4090
4091 return;
4092}
4093
4094void do_dmesg() {
4095 const char *title = "KERNEL LOG (dmesg)";
4096 DurationReporter duration_reporter(title);
4097 printf("------ %s ------\n", title);
4098
4099 if (PropertiesHelper::IsDryRun()) return;
4100
4101 /* Get size of kernel buffer */
4102 int size = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
4103 if (size <= 0) {
4104 printf("Unexpected klogctl return value: %d\n\n", size);
4105 return;
4106 }
4107 char *buf = (char *) malloc(size + 1);
4108 if (buf == nullptr) {
4109 printf("memory allocation failed\n\n");
4110 return;
4111 }
4112 int retval = klogctl(KLOG_READ_ALL, buf, size);
4113 if (retval < 0) {
4114 printf("klogctl failure\n\n");
4115 free(buf);
4116 return;
4117 }
4118 buf[retval] = '\0';
4119 printf("%s\n\n", buf);
4120 free(buf);
4121 return;
4122}
4123
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004124int Dumpstate::DumpFile(const std::string& title, const std::string& path) {
4125 DurationReporter duration_reporter(title);
4126
4127 int status = DumpFileToFd(STDOUT_FILENO, title, path);
4128
4129 UpdateProgress(WEIGHT_FILE);
4130
4131 return status;
4132}
4133
4134int read_file_as_long(const char *path, long int *output) {
4135 int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
4136 if (fd < 0) {
4137 int err = errno;
4138 MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
4139 return -1;
4140 }
4141 char buffer[50];
4142 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
4143 if (bytes_read == -1) {
4144 MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
4145 return -2;
4146 }
4147 if (bytes_read == 0) {
4148 MYLOGE("File %s is empty\n", path);
4149 return -3;
4150 }
4151 *output = atoi(buffer);
4152 return 0;
4153}
4154
4155/* calls skip to gate calling dump_from_fd recursively
4156 * in the specified directory. dump_from_fd defaults to
4157 * dump_file_from_fd above when set to NULL. skip defaults
4158 * to false when set to NULL. dump_from_fd will always be
4159 * called with title NULL.
4160 */
4161int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
4162 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4163 DurationReporter duration_reporter(title);
4164 DIR *dirp;
4165 struct dirent *d;
4166 char *newpath = nullptr;
4167 const char *slash = "/";
4168 int retval = 0;
4169
4170 if (!title.empty()) {
4171 printf("------ %s (%s) ------\n", title.c_str(), dir);
4172 }
4173 if (PropertiesHelper::IsDryRun()) return 0;
4174
4175 if (dir[strlen(dir) - 1] == '/') {
4176 ++slash;
4177 }
4178 dirp = opendir(dir);
4179 if (dirp == nullptr) {
4180 retval = -errno;
4181 MYLOGE("%s: %s\n", dir, strerror(errno));
4182 return retval;
4183 }
4184
4185 if (!dump_from_fd) {
4186 dump_from_fd = dump_file_from_fd;
4187 }
4188 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4189 if ((d->d_name[0] == '.')
4190 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4191 || (d->d_name[1] == '\0'))) {
4192 continue;
4193 }
4194 asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
4195 (d->d_type == DT_DIR) ? "/" : "");
4196 if (!newpath) {
4197 retval = -errno;
4198 continue;
4199 }
4200 if (skip && (*skip)(newpath)) {
4201 continue;
4202 }
4203 if (d->d_type == DT_DIR) {
4204 int ret = dump_files("", newpath, skip, dump_from_fd);
4205 if (ret < 0) {
4206 retval = ret;
4207 }
4208 continue;
4209 }
4210 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
4211 if (fd.get() < 0) {
4212 retval = -1;
4213 printf("*** %s: %s\n", newpath, strerror(errno));
4214 continue;
4215 }
4216 (*dump_from_fd)(nullptr, newpath, fd.get());
4217 }
4218 closedir(dirp);
4219 if (!title.empty()) {
4220 printf("\n");
4221 }
4222 return retval;
4223}
4224
4225/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
4226 * it's possible to avoid issues where opening the file itself can get
4227 * stuck.
4228 */
4229int dump_file_from_fd(const char *title, const char *path, int fd) {
4230 if (PropertiesHelper::IsDryRun()) return 0;
4231
4232 int flags = fcntl(fd, F_GETFL);
4233 if (flags == -1) {
4234 printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
4235 return -1;
4236 } else if (!(flags & O_NONBLOCK)) {
4237 printf("*** %s: fd must have O_NONBLOCK set.\n", path);
4238 return -1;
4239 }
4240 return DumpFileFromFdToFd(title, path, fd, STDOUT_FILENO, PropertiesHelper::IsDryRun());
4241}
4242
4243int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004244 const CommandOptions& options, bool verbose_duration, int out_fd) {
4245 DurationReporter duration_reporter(title, false /* logcat_only */,
4246 verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004247
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004248 int status = RunCommandToFd(out_fd, title, full_command, options);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004249
4250 /* TODO: for now we're simplifying the progress calculation by using the
4251 * timeout as the weight. It's a good approximation for most cases, except when calling dumpsys,
4252 * where its weight should be much higher proportionally to its timeout.
4253 * Ideally, it should use a options.EstimatedDuration() instead...*/
4254 UpdateProgress(options.Timeout());
4255
4256 return status;
4257}
4258
4259void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
Rhed Jaoe017f982020-07-21 17:58:41 +08004260 const CommandOptions& options, long dumpsysTimeoutMs, int out_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004261 long timeout_ms = dumpsysTimeoutMs > 0 ? dumpsysTimeoutMs : options.TimeoutInMs();
4262 std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-T", std::to_string(timeout_ms)};
4263 dumpsys.insert(dumpsys.end(), dumpsys_args.begin(), dumpsys_args.end());
Rhed Jaoe017f982020-07-21 17:58:41 +08004264 RunCommand(title, dumpsys, options, false, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004265}
4266
Dieter Hsu105ad0c2020-09-29 15:23:33 +08004267static int open_socket(const char* service) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004268 int s = android_get_control_socket(service);
4269 if (s < 0) {
4270 MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
4271 return -1;
4272 }
4273 fcntl(s, F_SETFD, FD_CLOEXEC);
4274
4275 // Set backlog to 0 to make sure that queue size will be minimum.
4276 // In Linux, because the minimum queue will be 1, connect() will be blocked
4277 // if the other clients already called connect() and the connection request was not accepted.
4278 if (listen(s, 0) < 0) {
4279 MYLOGE("listen(control socket): %s\n", strerror(errno));
4280 return -1;
4281 }
4282
4283 struct sockaddr addr;
4284 socklen_t alen = sizeof(addr);
Abhijeet Kaur2113cae2019-09-13 09:24:15 +01004285 int fd = accept4(s, &addr, &alen, SOCK_CLOEXEC);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004286
4287 // Close socket just after accept(), to make sure that connect() by client will get error
4288 // when the socket is used by the other services.
4289 // There is still a race condition possibility between accept and close, but there is no way
4290 // to close-on-accept atomically.
4291 // See detail; b/123306389#comment25
4292 close(s);
4293
4294 if (fd < 0) {
4295 MYLOGE("accept(control socket): %s\n", strerror(errno));
4296 return -1;
4297 }
4298
4299 return fd;
4300}
4301
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004302// TODO: should call is_valid_output_file and/or be merged into it.
4303void create_parent_dirs(const char *path) {
4304 char *chp = const_cast<char *> (path);
4305
4306 /* skip initial slash */
4307 if (chp[0] == '/')
4308 chp++;
4309
4310 /* create leading directories, if necessary */
4311 struct stat dir_stat;
4312 while (chp && chp[0]) {
4313 chp = strchr(chp, '/');
4314 if (chp) {
4315 *chp = 0;
4316 if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
4317 MYLOGI("Creating directory %s\n", path);
4318 if (mkdir(path, 0770)) { /* drwxrwx--- */
4319 MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
4320 } else if (chown(path, AID_SHELL, AID_SHELL)) {
4321 MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
4322 }
4323 }
4324 *chp++ = '/';
4325 }
4326 }
4327}
4328
4329bool _redirect_to_file(FILE* redirect, char* path, int truncate_flag) {
4330 create_parent_dirs(path);
4331
4332 int fd = TEMP_FAILURE_RETRY(open(path,
4333 O_WRONLY | O_CREAT | truncate_flag | O_CLOEXEC | O_NOFOLLOW,
4334 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
4335 if (fd < 0) {
4336 MYLOGE("%s: %s\n", path, strerror(errno));
4337 return false;
4338 }
4339
4340 TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
4341 close(fd);
4342 return true;
4343}
4344
4345bool redirect_to_file(FILE* redirect, char* path) {
4346 return _redirect_to_file(redirect, path, O_TRUNC);
4347}
4348
4349bool redirect_to_existing_file(FILE* redirect, char* path) {
4350 return _redirect_to_file(redirect, path, O_APPEND);
4351}
4352
4353void dump_route_tables() {
4354 DurationReporter duration_reporter("DUMP ROUTE TABLES");
4355 if (PropertiesHelper::IsDryRun()) return;
4356 const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
4357 ds.DumpFile("RT_TABLES", RT_TABLES_PATH);
4358 FILE* fp = fopen(RT_TABLES_PATH, "re");
4359 if (!fp) {
4360 printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
4361 return;
4362 }
4363 char table[16];
4364 // Each line has an integer (the table number), a space, and a string (the table name). We only
4365 // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
4366 // Add a fixed max limit so this doesn't go awry.
4367 for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
4368 RunCommand("ROUTE TABLE IPv4", {"ip", "-4", "route", "show", "table", table});
4369 RunCommand("ROUTE TABLE IPv6", {"ip", "-6", "route", "show", "table", table});
4370 }
4371 fclose(fp);
4372}
4373
Li Li830179f2022-01-04 12:53:29 -08004374void dump_frozen_cgroupfs(const char *dir, int level,
4375 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4376 DIR *dirp;
4377 struct dirent *d;
4378 char *newpath = nullptr;
4379
4380 dirp = opendir(dir);
4381 if (dirp == nullptr) {
4382 MYLOGE("%s: %s\n", dir, strerror(errno));
4383 return;
4384 }
4385
4386 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4387 if ((d->d_name[0] == '.')
4388 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4389 || (d->d_name[1] == '\0'))) {
4390 continue;
4391 }
4392 if (d->d_type == DT_DIR) {
4393 asprintf(&newpath, "%s/%s/", dir, d->d_name);
4394 if (!newpath) {
4395 continue;
4396 }
4397 if (level == 0 && !strncmp(d->d_name, "uid_", 4)) {
4398 dump_frozen_cgroupfs(newpath, 1, dump_from_fd);
4399 } else if (level == 1 && !strncmp(d->d_name, "pid_", 4)) {
4400 char *freezer = nullptr;
4401 asprintf(&freezer, "%s/%s", newpath, "cgroup.freeze");
4402 if (freezer) {
4403 FILE* fp = fopen(freezer, "r");
4404 if (fp != NULL) {
4405 int frozen;
4406 fscanf(fp, "%d", &frozen);
4407 if (frozen > 0) {
4408 dump_files("", newpath, skip_none, dump_from_fd);
4409 }
4410 fclose(fp);
4411 }
4412 free(freezer);
4413 }
4414 }
4415 }
4416 }
4417 closedir(dirp);
4418}
4419
4420void dump_frozen_cgroupfs() {
Li Li830179f2022-01-04 12:53:29 -08004421 MYLOGD("Adding frozen processes from %s\n", CGROUPFS_DIR);
4422 DurationReporter duration_reporter("FROZEN CGROUPFS");
4423 if (PropertiesHelper::IsDryRun()) return;
4424 dump_frozen_cgroupfs(CGROUPFS_DIR, 0, _add_file_from_fd);
4425}
4426
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004427void Dumpstate::UpdateProgress(int32_t delta_sec) {
4428 if (progress_ == nullptr) {
4429 MYLOGE("UpdateProgress: progress_ not set\n");
4430 return;
4431 }
Rhed Jaobf63d8a2020-07-21 15:42:55 +08004432 // This function updates progress related members of the dumpstate and reports
4433 // progress percentage to the bugreport client. Since it could be called by
4434 // different dump tasks at the same time if the parallel run is enabled, a
4435 // mutex lock is necessary here to synchronize the call.
4436 std::lock_guard<std::recursive_mutex> lock(mutex_);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004437
4438 // Always update progess so stats can be tuned...
Nandana Dutt402a8392019-06-14 14:25:13 +01004439 progress_->Inc(delta_sec);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004440
4441 // ...but only notifiy listeners when necessary.
4442 if (!options_->do_progress_updates) return;
4443
4444 int progress = progress_->Get();
4445 int max = progress_->GetMax();
Nandana Dutt402a8392019-06-14 14:25:13 +01004446 int percent = 100 * progress / max;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004447
Nandana Dutt402a8392019-06-14 14:25:13 +01004448 if (last_reported_percent_progress_ > 0 && percent <= last_reported_percent_progress_) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004449 return;
4450 }
Nandana Dutt402a8392019-06-14 14:25:13 +01004451 last_reported_percent_progress_ = percent;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004452
4453 if (control_socket_fd_ >= 0) {
4454 dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
4455 fsync(control_socket_fd_);
4456 }
4457
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004458 if (listener_ != nullptr) {
Nandana Dutt235c6672019-11-14 15:22:32 +00004459 if (percent % 10 == 0) {
4460 // We don't want to spam logcat, so only log multiples of 10.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004461 MYLOGD("Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004462 } else {
4463 // stderr is ignored on normal invocations, but useful when calling
4464 // /system/bin/dumpstate directly for debuggging.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004465 fprintf(stderr, "Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004466 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004467
4468 listener_->onProgress(percent);
4469 }
4470}
4471
4472void Dumpstate::TakeScreenshot(const std::string& path) {
4473 const std::string& real_path = path.empty() ? screenshot_path_ : path;
4474 int status =
4475 RunCommand("", {"/system/bin/screencap", "-p", real_path},
4476 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
4477 if (status == 0) {
4478 MYLOGD("Screenshot saved on %s\n", real_path.c_str());
4479 } else {
4480 MYLOGE("Failed to take screenshot on %s\n", real_path.c_str());
4481 }
Paul Chang0d2aad72020-02-13 20:04:03 +08004482 if (listener_ != nullptr) {
4483 // Show a visual indication to indicate screenshot is taken via
4484 // IDumpstateListener.onScreenshotTaken()
4485 listener_->onScreenshotTaken(status == 0);
4486 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004487}
4488
4489bool is_dir(const char* pathname) {
4490 struct stat info;
4491 if (stat(pathname, &info) == -1) {
4492 return false;
4493 }
4494 return S_ISDIR(info.st_mode);
4495}
4496
4497time_t get_mtime(int fd, time_t default_mtime) {
4498 struct stat info;
4499 if (fstat(fd, &info) == -1) {
4500 return default_mtime;
4501 }
4502 return info.st_mtime;
4503}