blob: b99f443fa69fce1b01625eb6c96c052fc38f401f [file] [log] [blame]
Colin Crossf45fa6b2012-03-26 12:38:26 -07001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Felipe Lemef0292972016-11-22 13:57:05 -080016
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070017#define LOG_TAG "dumpstate"
Kevin Jeon2c02e8e2022-07-07 21:45:17 +000018#define ATRACE_TAG ATRACE_TAG_ALWAYS
Colin Crossf45fa6b2012-03-26 12:38:26 -070019
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -070020#include <dirent.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070021#include <errno.h>
22#include <fcntl.h>
Nikita Ioffea325a572019-05-16 19:49:47 +010023#include <inttypes.h>
Felipe Lemead5f6c42015-11-30 14:26:46 -080024#include <libgen.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070025#include <limits.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010026#include <math.h>
27#include <poll.h>
Mark Salyzyn8f37aa52015-06-12 12:28:24 -070028#include <stdbool.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070029#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -070032#include <sys/mount.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080033#include <sys/poll.h>
Christopher Ferris7dc7f322014-07-22 16:08:19 -070034#include <sys/prctl.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070035#include <sys/resource.h>
36#include <sys/stat.h>
37#include <sys/time.h>
38#include <sys/wait.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010039#include <signal.h>
40#include <stdarg.h>
41#include <string.h>
42#include <sys/capability.h>
43#include <sys/inotify.h>
44#include <sys/klog.h>
45#include <time.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070046#include <unistd.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070047
48#include <chrono>
Hridya Valsarajuac582cd2019-08-05 15:39:54 -070049#include <cmath>
Abhijeet Kaurd3cca0d2019-03-25 12:04:16 +000050#include <fstream>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070051#include <functional>
52#include <future>
Narayan Kamath8f788292017-05-25 13:20:39 +010053#include <memory>
Hridya Valsarajuac582cd2019-08-05 15:39:54 -070054#include <numeric>
Narayan Kamath8f788292017-05-25 13:20:39 +010055#include <regex>
56#include <set>
57#include <string>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070058#include <utility>
Narayan Kamath8f788292017-05-25 13:20:39 +010059#include <vector>
Colin Crossf45fa6b2012-03-26 12:38:26 -070060
Kedar Chitnis9fd8c052021-11-16 09:09:22 +000061#include <aidl/android/hardware/dumpstate/IDumpstateDevice.h>
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +000062#include <android_app_admin_flags.h>
Felipe Leme96c2bbb2016-09-26 09:21:21 -070063#include <android-base/file.h>
64#include <android-base/properties.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070065#include <android-base/scopeguard.h>
Elliott Hughes9dc117c2015-12-07 14:21:50 -080066#include <android-base/stringprintf.h>
Naveen Kalla058e1e82016-10-19 21:38:44 -070067#include <android-base/strings.h>
Andreas Gampeaff68432016-07-18 18:01:27 -070068#include <android-base/unique_fd.h>
Kedar Chitnis9fd8c052021-11-16 09:09:22 +000069#include <android/binder_manager.h>
70#include <android/binder_process.h>
Nikita Ioffea325a572019-05-16 19:49:47 +010071#include <android/content/pm/IPackageManagerNative.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080072#include <android/hardware/dumpstate/1.0/IDumpstateDevice.h>
Hunter Knepshield8540faf2020-02-04 19:47:20 -080073#include <android/hardware/dumpstate/1.1/IDumpstateDevice.h>
74#include <android/hardware/dumpstate/1.1/types.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080075#include <android/hidl/manager/1.0/IServiceManager.h>
Nandana Duttd2f5f082019-01-18 17:13:52 +000076#include <android/os/IIncidentCompanion.h>
Nikita Ioffea325a572019-05-16 19:49:47 +010077#include <binder/IServiceManager.h>
Nikhil Kumar28ce35e2023-01-10 14:32:44 +000078#include <cutils/multiuser.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080079#include <cutils/native_handle.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070080#include <cutils/properties.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010081#include <cutils/sockets.h>
Kevin Jeon2c02e8e2022-07-07 21:45:17 +000082#include <cutils/trace.h>
Nandana Duttfaafd522019-03-11 09:23:09 +000083#include <debuggerd/client.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080084#include <dumpsys.h>
Nandana Duttfaafd522019-03-11 09:23:09 +000085#include <dumputils/dump_utils.h>
Sahana Raof35ed432019-07-12 10:47:52 +010086#include <hardware_legacy/power.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080087#include <hidl/ServiceManagement.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010088#include <log/log.h>
Tom Cherryf4472f32020-08-05 09:31:17 -070089#include <log/log_read.h>
Felipe Leme75876a22016-10-27 16:31:27 -070090#include <openssl/sha.h>
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070091#include <private/android_filesystem_config.h>
92#include <private/android_logger.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080093#include <serviceutils/PriorityDumper.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070094#include <utils/StrongPointer.h>
Devin Moore8df81bb2022-06-08 22:47:02 +000095#include <vintf/VintfObject.h>
Felipe Lemef0292972016-11-22 13:57:05 -080096#include "DumpstateInternal.h"
Felipe Leme75876a22016-10-27 16:31:27 -070097#include "DumpstateService.h"
Colin Crossf45fa6b2012-03-26 12:38:26 -070098#include "dumpstate.h"
Felipe Leme6e01fa62015-11-11 19:35:14 -080099
Kedar Chitnis9fd8c052021-11-16 09:09:22 +0000100namespace dumpstate_hal_hidl_1_0 = android::hardware::dumpstate::V1_0;
101namespace dumpstate_hal_hidl = android::hardware::dumpstate::V1_1;
102namespace dumpstate_hal_aidl = aidl::android::hardware::dumpstate;
103
Vishnu Naire97d6122018-01-18 13:58:56 -0800104using ::std::literals::chrono_literals::operator""ms;
105using ::std::literals::chrono_literals::operator""s;
Rhed Jao5377d792020-07-16 17:37:39 +0800106using ::std::placeholders::_1;
Steven Morelandcb7ef822016-11-29 13:20:37 -0800107
Felipe Leme47e9be22016-12-21 15:37:07 -0800108// TODO: remove once moved to namespace
Vishnu Naire97d6122018-01-18 13:58:56 -0800109using android::defaultServiceManager;
110using android::Dumpsys;
111using android::INVALID_OPERATION;
112using android::IServiceManager;
113using android::OK;
114using android::sp;
115using android::status_t;
116using android::String16;
117using android::String8;
118using android::TIMED_OUT;
119using android::UNKNOWN_ERROR;
120using android::Vector;
Nandana Dutt979388e2018-11-30 16:48:55 +0000121using android::base::StringPrintf;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000122using android::os::IDumpstateListener;
Felipe Leme47e9be22016-12-21 15:37:07 -0800123using android::os::dumpstate::CommandOptions;
124using android::os::dumpstate::DumpFileToFd;
Rhed Jao5377d792020-07-16 17:37:39 +0800125using android::os::dumpstate::DumpPool;
Vishnu Naire97d6122018-01-18 13:58:56 -0800126using android::os::dumpstate::PropertiesHelper;
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800127using android::os::dumpstate::TaskQueue;
Chris Morinbc223142022-02-04 14:17:11 -0800128using android::os::dumpstate::WaitForTask;
Felipe Leme47e9be22016-12-21 15:37:07 -0800129
Abhijeet Kaurcf234e82019-07-01 14:53:55 +0100130// Keep in sync with
131// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
132static const int TRACE_DUMP_TIMEOUT_MS = 10000; // 10 seconds
133
134/* Most simple commands have 10 as timeout, so 5 is a good estimate */
135static const int32_t WEIGHT_FILE = 5;
136
137// TODO: temporary variables and functions used during C++ refactoring
138static Dumpstate& ds = Dumpstate::GetInstance();
139static int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Nandana Dutt8d945c02019-08-14 13:30:07 +0100140 const CommandOptions& options = CommandOptions::DEFAULT,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800141 bool verbose_duration = false, int out_fd = STDOUT_FILENO) {
142 return ds.RunCommand(title, full_command, options, verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +0100143}
144
145// Reasonable value for max stats.
146static const int STATS_MAX_N_RUNS = 1000;
147static const long STATS_MAX_AVERAGE = 100000;
148
149CommandOptions Dumpstate::DEFAULT_DUMPSYS = CommandOptions::WithTimeout(30).Build();
150
Nandana Duttd2f5f082019-01-18 17:13:52 +0000151typedef Dumpstate::ConsentCallback::ConsentResult UserConsentResult;
152
Colin Crossf45fa6b2012-03-26 12:38:26 -0700153/* read before root is shed */
154static char cmdline_buf[16384] = "(unknown)";
Yi Kong19d5c002018-07-20 13:39:55 -0700155static const char *dump_traces_path = nullptr;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000156static const uint64_t USER_CONSENT_TIMEOUT_MS = 30 * 1000;
Hunter Knepshield70610fa2020-01-03 15:27:33 -0800157// Because telephony reports are significantly faster to collect (< 10 seconds vs. > 2 minutes),
158// it's often the case that they time out far too quickly for consent with such a hefty dialog for
159// the user to read. For telephony reports only, we increase the default timeout to 2 minutes to
160// roughly match full reports' durations.
161static const uint64_t TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS = 2 * 60 * 1000;
Colin Crossf45fa6b2012-03-26 12:38:26 -0700162
Felipe Leme1d486fe2016-10-14 18:06:47 -0700163// TODO: variables and functions below should be part of dumpstate object
164
Felipe Leme635ca312016-01-05 14:23:02 -0800165static std::set<std::string> mount_points;
166void add_mountinfo();
Felipe Leme78f2c862015-12-21 09:55:22 -0800167
Todd Poynor2a83daa2013-11-22 15:44:22 -0800168#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
Mark Salyzyn7d0a7622016-06-24 14:06:15 -0700169#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
Wei Wang509bb5d2017-06-09 14:42:12 -0700170#define BLK_DEV_SYS_DIR "/sys/block"
Todd Poynor2a83daa2013-11-22 15:44:22 -0800171
Felipe Lemee82a27d2016-01-05 13:35:44 -0800172#define RECOVERY_DIR "/cache/recovery"
Mark Salyzynd6ab0112016-03-25 12:56:39 -0700173#define RECOVERY_DATA_DIR "/data/misc/recovery"
Tianjie Xu75d53362018-04-11 16:42:28 -0700174#define UPDATE_ENGINE_LOG_DIR "/data/misc/update_engine_log"
Kelvin Zhang6eaa0f92022-09-12 09:29:19 -0700175#define UPDATE_ENGINE_PREF_DIR "/data/misc/update_engine/prefs"
Mark Salyzyn4d42dea2016-04-01 10:03:14 -0700176#define LOGPERSIST_DATA_DIR "/data/misc/logd"
Jerry Changa1df8a92020-01-02 16:03:39 +0800177#define PREREBOOT_DATA_DIR "/data/misc/prereboot"
David Brazdild2991962016-06-03 14:40:44 +0100178#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
179#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
Benedict Wong8f9d8a42019-01-03 16:19:38 -0800180#define XFRM_STAT_PROC_FILE "/proc/net/xfrm_stat"
Steven Moreland9379c462023-12-21 02:04:27 +0000181#define KERNEL_CONFIG "/proc/config.gz"
Erik Kline08165202016-05-30 11:55:44 +0900182#define WLUTIL "/vendor/xbin/wlutil"
Vishnu Nair36b4cdb2017-11-17 10:27:05 -0800183#define WMTRACE_DATA_DIR "/data/misc/wmtrace"
Yifan Hong3945e1b2019-10-29 12:59:23 -0700184#define OTA_METADATA_DIR "/metadata/ota"
Yifan Hong0efa7972020-02-03 16:45:02 -0800185#define SNAPSHOTCTL_LOG_DIR "/data/misc/snapshotctl_log"
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +0900186#define LINKERCONFIG_DIR "/linkerconfig"
Calin Juravlef84d3692020-04-28 15:31:12 -0700187#define PACKAGE_DEX_USE_LIST "/data/system/package-dex-usage.list"
Primiano Tuccifaaaafb2021-01-14 12:26:29 +0000188#define SYSTEM_TRACE_SNAPSHOT "/data/misc/perfetto-traces/bugreport/systrace.pftrace"
Li Li2eedd412021-06-30 15:11:53 -0700189#define CGROUPFS_DIR "/sys/fs/cgroup"
Mårten Kongstad60195a72022-09-20 14:14:20 +0200190#define SDK_EXT_INFO "/apex/com.android.sdkext/bin/derive_sdk"
Jeff Sharkey9df29d52023-02-06 14:26:30 -0700191#define DROPBOX_DIR "/data/system/dropbox"
Mårten Kongstad5ad813f2023-09-28 10:09:18 +0200192#define PRINT_FLAGS "/system/bin/printflags"
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700193
Narayan Kamath8f788292017-05-25 13:20:39 +0100194// TODO(narayan): Since this information has to be kept in sync
195// with tombstoned, we should just put it in a common header.
196//
197// File: system/core/debuggerd/tombstoned/tombstoned.cpp
Narayan Kamathbd863722017-06-01 18:50:12 +0100198static const std::string TOMBSTONE_DIR = "/data/tombstones/";
199static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
200static const std::string ANR_DIR = "/data/anr/";
201static const std::string ANR_FILE_PREFIX = "anr_";
Woody Lin20767a92022-11-29 15:50:24 +0800202static const std::string SHUTDOWN_CHECKPOINTS_DIR = "/data/system/shutdown-checkpoints/";
203static const std::string SHUTDOWN_CHECKPOINTS_FILE_PREFIX = "checkpoints-";
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700204
Felipe Lemee844a9d2016-09-21 15:01:39 -0700205// TODO: temporary variables and functions used during C++ refactoring
Nandana Dutt979388e2018-11-30 16:48:55 +0000206
Nandana Dutt5c390032019-03-12 10:52:56 +0000207#define RETURN_IF_USER_DENIED_CONSENT() \
208 if (ds.IsUserConsentDenied()) { \
209 MYLOGE("Returning early as user denied consent to share bugreport with calling app."); \
210 return Dumpstate::RunStatus::USER_CONSENT_DENIED; \
211 }
212
213// Runs func_ptr, but checks user consent before and after running it. Returns USER_CONSENT_DENIED
214// if consent is found to be denied.
215#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(func_ptr, ...) \
216 RETURN_IF_USER_DENIED_CONSENT(); \
217 func_ptr(__VA_ARGS__); \
218 RETURN_IF_USER_DENIED_CONSENT();
219
Rhed Jao5377d792020-07-16 17:37:39 +0800220// Runs func_ptr, and logs a duration report after it's finished.
221#define RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, ...) \
222 { \
223 DurationReporter duration_reporter_in_macro(log_title); \
224 func_ptr(__VA_ARGS__); \
225 }
226
227// Similar with RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK, an additional duration report
228// is output after a slow function is finished.
229#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(log_title, func_ptr, ...) \
230 RETURN_IF_USER_DENIED_CONSENT(); \
231 RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, __VA_ARGS__); \
232 RETURN_IF_USER_DENIED_CONSENT();
233
Chris Morinbc223142022-02-04 14:17:11 -0800234#define WAIT_TASK_WITH_CONSENT_CHECK(future) \
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800235 RETURN_IF_USER_DENIED_CONSENT(); \
Chris Morinbc223142022-02-04 14:17:11 -0800236 WaitForTask(future); \
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800237 RETURN_IF_USER_DENIED_CONSENT();
238
Sahana Raof35ed432019-07-12 10:47:52 +0100239static const char* WAKE_LOCK_NAME = "dumpstate_wakelock";
240
Rhed Jao5377d792020-07-16 17:37:39 +0800241// Names of parallel tasks, they are used for the DumpPool to identify the dump
242// task and the log title of the duration report.
243static const std::string DUMP_TRACES_TASK = "DUMP TRACES";
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800244static const std::string DUMP_INCIDENT_REPORT_TASK = "INCIDENT REPORT";
Aaron Huang24d215d2022-04-27 18:51:16 +0800245static const std::string DUMP_NETSTATS_PROTO_TASK = "DUMP NETSTATS PROTO";
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800246static const std::string DUMP_HALS_TASK = "DUMP HALS";
247static const std::string DUMP_BOARD_TASK = "dumpstate_board()";
Rhed Jaoe017f982020-07-21 17:58:41 +0800248static const std::string DUMP_CHECKINS_TASK = "DUMP CHECKINS";
Kean Mariotti306633e2022-09-05 16:30:47 +0000249static const std::string POST_PROCESS_UI_TRACES_TASK = "POST-PROCESS UI TRACES";
Rhed Jao5377d792020-07-16 17:37:39 +0800250
Nandana Dutt979388e2018-11-30 16:48:55 +0000251namespace android {
252namespace os {
253namespace {
254
255static int Open(std::string path, int flags, mode_t mode = 0) {
256 int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
257 if (fd == -1) {
258 MYLOGE("open(%s, %s)\n", path.c_str(), strerror(errno));
259 }
260 return fd;
261}
262
mhasank2d75c442020-06-11 15:05:25 -0700263static int OpenForWrite(std::string path) {
264 return Open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
265 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
266}
Nandana Dutt979388e2018-11-30 16:48:55 +0000267
268static int OpenForRead(std::string path) {
269 return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
270}
271
272bool CopyFile(int in_fd, int out_fd) {
273 char buf[4096];
274 ssize_t byte_count;
275 while ((byte_count = TEMP_FAILURE_RETRY(read(in_fd, buf, sizeof(buf)))) > 0) {
276 if (!android::base::WriteFully(out_fd, buf, byte_count)) {
277 return false;
278 }
279 }
280 return (byte_count != -1);
281}
282
283static bool CopyFileToFd(const std::string& input_file, int out_fd) {
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000284 MYLOGD("Going to copy file (%s) to %d\n", input_file.c_str(), out_fd);
Nandana Dutt979388e2018-11-30 16:48:55 +0000285
286 // Obtain a handle to the source file.
287 android::base::unique_fd in_fd(OpenForRead(input_file));
288 if (out_fd != -1 && in_fd.get() != -1) {
289 if (CopyFile(in_fd.get(), out_fd)) {
290 return true;
291 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000292 MYLOGE("Failed to copy file: %s\n", strerror(errno));
Nandana Dutt979388e2018-11-30 16:48:55 +0000293 }
294 return false;
295}
296
Nandana Duttd2f5f082019-01-18 17:13:52 +0000297static bool UnlinkAndLogOnError(const std::string& file) {
Nandana Dutt8ae16e62020-03-27 10:20:22 +0000298 if (file.empty()) {
299 return false;
300 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000301 if (unlink(file.c_str())) {
302 MYLOGE("Failed to unlink file (%s): %s\n", file.c_str(), strerror(errno));
Nandana Duttd2f5f082019-01-18 17:13:52 +0000303 return false;
304 }
305 return true;
306}
Nandana Dutt979388e2018-11-30 16:48:55 +0000307
Nikita Ioffea325a572019-05-16 19:49:47 +0100308int64_t GetModuleMetadataVersion() {
309 auto binder = defaultServiceManager()->getService(android::String16("package_native"));
310 if (binder == nullptr) {
311 MYLOGE("Failed to retrieve package_native service");
312 return 0L;
313 }
314 auto package_service = android::interface_cast<content::pm::IPackageManagerNative>(binder);
315 std::string package_name;
316 auto status = package_service->getModuleMetadataPackageName(&package_name);
317 if (!status.isOk()) {
318 MYLOGE("Failed to retrieve module metadata package name: %s", status.toString8().c_str());
319 return 0L;
320 }
Nandana Duttdb379fa2019-10-09 16:54:41 +0100321 MYLOGD("Module metadata package name: %s\n", package_name.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100322 int64_t version_code;
323 status = package_service->getVersionCodeForPackage(android::String16(package_name.c_str()),
324 &version_code);
325 if (!status.isOk()) {
326 MYLOGE("Failed to retrieve module metadata version: %s", status.toString8().c_str());
327 return 0L;
328 }
329 return version_code;
330}
331
mhasank2d75c442020-06-11 15:05:25 -0700332static bool PathExists(const std::string& path) {
333 struct stat sb;
334 return stat(path.c_str(), &sb) == 0;
335}
336
337static bool CopyFileToFile(const std::string& input_file, const std::string& output_file) {
338 if (input_file == output_file) {
339 MYLOGD("Skipping copying bugreport file since the destination is the same (%s)\n",
340 output_file.c_str());
341 return false;
342 }
343 else if (PathExists(output_file)) {
344 MYLOGD("Cannot overwrite an existing file (%s)\n", output_file.c_str());
345 return false;
346 }
347
348 MYLOGD("Going to copy bugreport file (%s) to %s\n", input_file.c_str(), output_file.c_str());
349 android::base::unique_fd out_fd(OpenForWrite(output_file));
350 return CopyFileToFd(input_file, out_fd.get());
351}
352
Nandana Dutt979388e2018-11-30 16:48:55 +0000353} // namespace
354} // namespace os
355} // namespace android
356
Felipe Leme678727a2016-09-21 17:22:11 -0700357static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
Felipe Lemebda15a02016-11-16 17:48:25 -0800358 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
Rhed Jaoe017f982020-07-21 17:58:41 +0800359 long dumpsysTimeoutMs = 0, int out_fd = STDOUT_FILENO) {
360 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs, out_fd);
361}
362static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
363 int out_fd) {
364 return ds.RunDumpsys(title, dumpsysArgs, Dumpstate::DEFAULT_DUMPSYS, 0, out_fd);
Felipe Leme678727a2016-09-21 17:22:11 -0700365}
366static int DumpFile(const std::string& title, const std::string& path) {
367 return ds.DumpFile(title, path);
368}
Felipe Lemee82a27d2016-01-05 13:35:44 -0800369
Felipe Lemee844a9d2016-09-21 15:01:39 -0700370// Relative directory (inside the zip) for all files copied as-is into the bugreport.
371static const std::string ZIP_ROOT_DIR = "FS";
372
Vishnu Naire97d6122018-01-18 13:58:56 -0800373static const std::string kProtoPath = "proto/";
374static const std::string kProtoExt = ".proto";
Jie Song9fbfad02017-06-20 16:29:42 -0700375static const std::string kDumpstateBoardFiles[] = {
376 "dumpstate_board.txt",
Felipe Leme95d6ca52017-08-01 16:35:56 -0700377 "dumpstate_board.bin"
Jie Song9fbfad02017-06-20 16:29:42 -0700378};
379static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
380
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700381static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Lemed071c682016-10-20 16:48:00 -0700382static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700383
Felipe Lemef0292972016-11-22 13:57:05 -0800384static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
385
Narayan Kamath8f788292017-05-25 13:20:39 +0100386/*
Narayan Kamathbd863722017-06-01 18:50:12 +0100387 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
Rhed Jao01dc0c62020-06-03 17:13:30 +0800388 * The returned vector is sorted by the mtimes of the dumps with descending
Chris Morinc2cba7a2022-02-01 17:06:50 -0800389 * order.
Narayan Kamath8f788292017-05-25 13:20:39 +0100390 */
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700391static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
Chris Morinc2cba7a2022-02-01 17:06:50 -0800392 const std::string& file_prefix) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100393 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100394
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700395 if (dump_dir == nullptr) {
396 MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno));
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700397 return std::vector<DumpData>();
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700398 }
399
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700400 std::vector<DumpData> dump_data;
Narayan Kamathbd863722017-06-01 18:50:12 +0100401 struct dirent* entry = nullptr;
402 while ((entry = readdir(dump_dir.get()))) {
403 if (entry->d_type != DT_REG) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100404 continue;
405 }
406
Narayan Kamathbd863722017-06-01 18:50:12 +0100407 const std::string base_name(entry->d_name);
408 if (base_name.find(file_prefix) != 0) {
409 continue;
410 }
411
412 const std::string abs_path = dir_path + base_name;
413 android::base::unique_fd fd(
414 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
415 if (fd == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700416 MYLOGW("Unable to open dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamathbd863722017-06-01 18:50:12 +0100417 break;
418 }
419
420 struct stat st = {};
421 if (fstat(fd, &st) == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700422 MYLOGW("Unable to stat dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamath8f788292017-05-25 13:20:39 +0100423 continue;
424 }
425
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700426 dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700427 }
Rhed Jao01dc0c62020-06-03 17:13:30 +0800428 if (!dump_data.empty()) {
429 std::sort(dump_data.begin(), dump_data.end(),
430 [](const auto& a, const auto& b) { return a.mtime > b.mtime; });
431 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100432
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700433 return dump_data;
Narayan Kamath8f788292017-05-25 13:20:39 +0100434}
435
Narayan Kamathbd863722017-06-01 18:50:12 +0100436static bool AddDumps(const std::vector<DumpData>::const_iterator start,
437 const std::vector<DumpData>::const_iterator end,
438 const char* type_name, const bool add_to_zip) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100439 bool dumped = false;
Narayan Kamathbd863722017-06-01 18:50:12 +0100440 for (auto it = start; it != end; ++it) {
441 const std::string& name = it->name;
442 const int fd = it->fd;
Narayan Kamath8f788292017-05-25 13:20:39 +0100443 dumped = true;
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100444
445 // Seek to the beginning of the file before dumping any data. A given
446 // DumpData entry might be dumped multiple times in the report.
447 //
448 // For example, the most recent ANR entry is dumped to the body of the
449 // main entry and it also shows up as a separate entry in the bugreport
450 // ZIP file.
451 if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) {
452 MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(),
453 strerror(errno));
454 }
455
Chris Morinc2cba7a2022-02-01 17:06:50 -0800456 if (add_to_zip) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800457 if (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd, /* timeout = */ 0ms) != OK) {
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100458 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100459 }
460 } else {
461 dump_file_from_fd(type_name, name.c_str(), fd);
462 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100463 }
464
465 return dumped;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700466}
467
Felipe Leme635ca312016-01-05 14:23:02 -0800468// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700469void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800470 char path[PATH_MAX];
471
472 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
473 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700474 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800475 char linkname[PATH_MAX];
476 ssize_t r = readlink(path, linkname, PATH_MAX);
477 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800478 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800479 return;
480 }
481 linkname[r] = '\0';
482
483 if (mount_points.find(linkname) == mount_points.end()) {
484 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700485 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700486 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
Felipe Leme635ca312016-01-05 14:23:02 -0800487 mount_points.insert(linkname);
488 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800489 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800490 }
491 }
492}
493
494void add_mountinfo() {
Felipe Leme678727a2016-09-21 17:22:11 -0700495 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800496 mount_points.clear();
Felipe Leme46b85da2016-11-21 17:40:45 -0800497 DurationReporter duration_reporter(title, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700498 for_each_pid(do_mountinfo, nullptr);
499 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800500}
501
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700502static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
503{
504 DIR *d;
505 struct dirent *de;
506 char path[PATH_MAX];
507
508 d = opendir(driverpath);
Yi Kong19d5c002018-07-20 13:39:55 -0700509 if (d == nullptr) {
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700510 return;
511 }
512
513 while ((de = readdir(d))) {
514 if (de->d_type != DT_LNK) {
515 continue;
516 }
517 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700518 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700519 }
520
521 closedir(d);
522}
523
Mark Salyzyn326842f2015-04-30 09:49:41 -0700524static bool skip_not_stat(const char *path) {
525 static const char stat[] = "/stat";
526 size_t len = strlen(path);
527 if (path[len - 1] == '/') { /* Directory? */
528 return false;
529 }
530 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
531}
532
Jeff Sharkey9df29d52023-02-06 14:26:30 -0700533static bool skip_wtf_strictmode(const char *path) {
534 if (strstr(path, "_wtf")) {
535 return true;
536 } else if (strstr(path, "_strictmode")) {
537 return true;
538 }
539 return false;
540}
541
Felipe Leme4c2d6632016-09-28 14:32:00 -0700542static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800543 return false;
544}
545
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700546unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700547
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800548//
549// stat offsets
550// Name units description
551// ---- ----- -----------
552// read I/Os requests number of read I/Os processed
553#define __STAT_READ_IOS 0
554// read merges requests number of read I/Os merged with in-queue I/O
555#define __STAT_READ_MERGES 1
556// read sectors sectors number of sectors read
557#define __STAT_READ_SECTORS 2
558// read ticks milliseconds total wait time for read requests
559#define __STAT_READ_TICKS 3
560// write I/Os requests number of write I/Os processed
561#define __STAT_WRITE_IOS 4
562// write merges requests number of write I/Os merged with in-queue I/O
563#define __STAT_WRITE_MERGES 5
564// write sectors sectors number of sectors written
565#define __STAT_WRITE_SECTORS 6
566// write ticks milliseconds total wait time for write requests
567#define __STAT_WRITE_TICKS 7
568// in_flight requests number of I/Os currently in flight
569#define __STAT_IN_FLIGHT 8
570// io_ticks milliseconds total time this block device has been active
571#define __STAT_IO_TICKS 9
572// time_in_queue milliseconds total wait time for all requests
573#define __STAT_IN_QUEUE 10
574#define __STAT_NUMBER_FIELD 11
575//
576// read I/Os, write I/Os
577// =====================
578//
579// These values increment when an I/O request completes.
580//
581// read merges, write merges
582// =========================
583//
584// These values increment when an I/O request is merged with an
585// already-queued I/O request.
586//
587// read sectors, write sectors
588// ===========================
589//
590// These values count the number of sectors read from or written to this
591// block device. The "sectors" in question are the standard UNIX 512-byte
592// sectors, not any device- or filesystem-specific block size. The
593// counters are incremented when the I/O completes.
594#define SECTOR_SIZE 512
595//
596// read ticks, write ticks
597// =======================
598//
599// These values count the number of milliseconds that I/O requests have
600// waited on this block device. If there are multiple I/O requests waiting,
601// these values will increase at a rate greater than 1000/second; for
602// example, if 60 read requests wait for an average of 30 ms, the read_ticks
603// field will increase by 60*30 = 1800.
604//
605// in_flight
606// =========
607//
608// This value counts the number of I/O requests that have been issued to
609// the device driver but have not yet completed. It does not include I/O
610// requests that are in the queue but not yet issued to the device driver.
611//
612// io_ticks
613// ========
614//
615// This value counts the number of milliseconds during which the device has
616// had I/O requests queued.
617//
618// time_in_queue
619// =============
620//
621// This value counts the number of milliseconds that I/O requests have waited
622// on this block device. If there are multiple I/O requests waiting, this
623// value will increase as the product of the number of milliseconds times the
624// number of requests waiting (see "read ticks" above for an example).
625#define S_TO_MS 1000
626//
627
Mark Salyzyn326842f2015-04-30 09:49:41 -0700628static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800629 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700630 bool z;
Yi Kong19d5c002018-07-20 13:39:55 -0700631 char *cp, *buffer = nullptr;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700632 size_t i = 0;
Josh Gao7c4258c2018-06-25 13:40:08 -0700633 FILE *fp = fdopen(dup(fd), "rb");
Mark Salyzyn326842f2015-04-30 09:49:41 -0700634 getline(&buffer, &i, fp);
635 fclose(fp);
636 if (!buffer) {
637 return -errno;
638 }
639 i = strlen(buffer);
640 while ((i > 0) && (buffer[i - 1] == '\n')) {
641 buffer[--i] = '\0';
642 }
643 if (!*buffer) {
644 free(buffer);
645 return 0;
646 }
647 z = true;
648 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800649 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700650 if (fields[i] != 0) {
651 z = false;
652 }
653 }
654 if (z) { /* never accessed */
655 free(buffer);
656 return 0;
657 }
658
Wei Wang509bb5d2017-06-09 14:42:12 -0700659 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
660 path += sizeof(BLK_DEV_SYS_DIR) - 1;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700661 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700662
663 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
664 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
665 "W-wait", "in-fli", "activ", "T-wait", path, buffer);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700666 free(buffer);
667
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800668 if (fields[__STAT_IO_TICKS]) {
669 unsigned long read_perf = 0;
670 unsigned long read_ios = 0;
671 if (fields[__STAT_READ_TICKS]) {
672 unsigned long long divisor = fields[__STAT_READ_TICKS]
673 * fields[__STAT_IO_TICKS];
674 read_perf = ((unsigned long long)SECTOR_SIZE
675 * fields[__STAT_READ_SECTORS]
676 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
677 / divisor;
678 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
679 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
680 / divisor;
681 }
682
683 unsigned long write_perf = 0;
684 unsigned long write_ios = 0;
685 if (fields[__STAT_WRITE_TICKS]) {
686 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
687 * fields[__STAT_IO_TICKS];
688 write_perf = ((unsigned long long)SECTOR_SIZE
689 * fields[__STAT_WRITE_SECTORS]
690 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
691 / divisor;
692 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
693 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
694 / divisor;
695 }
696
697 unsigned queue = (fields[__STAT_IN_QUEUE]
698 + (fields[__STAT_IO_TICKS] >> 1))
699 / fields[__STAT_IO_TICKS];
700
701 if (!write_perf && !write_ios) {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700702 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 -0800703 } else {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700704 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 -0800705 read_ios, write_perf, write_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800706 }
707
708 /* bugreport timeout factor adjustment */
709 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
710 worst_write_perf = write_perf;
711 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700712 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700713 return 0;
714}
715
Yao Chenbe3bbc12018-01-17 16:31:10 -0800716static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
717
Tom Cherryf4472f32020-08-05 09:31:17 -0700718// Returns the actual readable size of the given buffer or -1 on error.
719static long logcat_buffer_readable_size(const std::string& buffer) {
720 std::unique_ptr<logger_list, decltype(&android_logger_list_free)> logger_list{
721 android_logger_list_alloc(0, 0, 0), &android_logger_list_free};
722 auto logger = android_logger_open(logger_list.get(), android_name_to_log_id(buffer.c_str()));
723
724 return android_logger_get_log_readable_size(logger);
725}
726
727// Returns timeout in ms to read a list of buffers.
Yao Chenbe3bbc12018-01-17 16:31:10 -0800728static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
729 unsigned long timeout_ms = 0;
730 for (const auto& buffer : buffers) {
Tom Cherryf4472f32020-08-05 09:31:17 -0700731 long readable_size = logcat_buffer_readable_size(buffer);
732 if (readable_size > 0) {
733 // Engineering margin is ten-fold our guess.
734 timeout_ms += 10 * (readable_size + worst_write_perf) / worst_write_perf;
735 }
Yao Chenbe3bbc12018-01-17 16:31:10 -0800736 }
737 return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700738}
739
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800740// Opens a socket and returns its file descriptor.
741static int open_socket(const char* service);
742
Nandana Duttd2f5f082019-01-18 17:13:52 +0000743Dumpstate::ConsentCallback::ConsentCallback() : result_(UNAVAILABLE), start_time_(Nanotime()) {
744}
745
746android::binder::Status Dumpstate::ConsentCallback::onReportApproved() {
747 std::lock_guard<std::mutex> lock(lock_);
748 result_ = APPROVED;
749 MYLOGD("User approved consent to share bugreport\n");
Paul Chang0d2aad72020-02-13 20:04:03 +0800750
751 // Maybe copy screenshot so calling app can display the screenshot to the user as soon as
752 // consent is granted.
753 if (ds.options_->is_screenshot_copied) {
754 return android::binder::Status::ok();
755 }
756
757 if (!ds.options_->do_screenshot || ds.options_->screenshot_fd.get() == -1 ||
758 !ds.do_early_screenshot_) {
759 return android::binder::Status::ok();
760 }
761
762 bool copy_succeeded = android::os::CopyFileToFd(ds.screenshot_path_,
763 ds.options_->screenshot_fd.get());
764 ds.options_->is_screenshot_copied = copy_succeeded;
765 if (copy_succeeded) {
766 android::os::UnlinkAndLogOnError(ds.screenshot_path_);
767 }
Nandana Duttd2f5f082019-01-18 17:13:52 +0000768 return android::binder::Status::ok();
769}
770
771android::binder::Status Dumpstate::ConsentCallback::onReportDenied() {
772 std::lock_guard<std::mutex> lock(lock_);
773 result_ = DENIED;
774 MYLOGW("User denied consent to share bugreport\n");
775 return android::binder::Status::ok();
776}
777
778UserConsentResult Dumpstate::ConsentCallback::getResult() {
779 std::lock_guard<std::mutex> lock(lock_);
780 return result_;
781}
782
783uint64_t Dumpstate::ConsentCallback::getElapsedTimeMs() const {
Hunter Knepshieldf0a39052020-01-03 14:53:04 -0800784 return (Nanotime() - start_time_) / NANOS_PER_MILLI;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000785}
786
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700787void Dumpstate::PrintHeader() const {
Mårten Kongstad60195a72022-09-20 14:14:20 +0200788 std::string build, fingerprint, radio, bootloader, network, sdkversion;
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700789 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700790
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700791 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
792 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700793 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
794 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
795 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
Mårten Kongstad60195a72022-09-20 14:14:20 +0200796 sdkversion = android::base::GetProperty("ro.build.version.sdk", "(unknown)");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700797 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
Colin Crossf45fa6b2012-03-26 12:38:26 -0700798
Felipe Lemed8b94e52016-12-08 10:21:44 -0800799 printf("========================================================\n");
800 printf("== dumpstate: %s\n", date);
801 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700802
Felipe Lemed8b94e52016-12-08 10:21:44 -0800803 printf("\n");
804 printf("Build: %s\n", build.c_str());
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700805 // NOTE: fingerprint entry format is important for other tools.
Felipe Lemed8b94e52016-12-08 10:21:44 -0800806 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
807 printf("Bootloader: %s\n", bootloader.c_str());
808 printf("Radio: %s\n", radio.c_str());
809 printf("Network: %s\n", network.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100810 int64_t module_metadata_version = android::os::GetModuleMetadataVersion();
811 if (module_metadata_version != 0) {
812 printf("Module Metadata version: %" PRId64 "\n", module_metadata_version);
813 }
Mårten Kongstad60195a72022-09-20 14:14:20 +0200814 printf("Android SDK version: %s\n", sdkversion.c_str());
815 printf("SDK extensions: ");
816 RunCommandToFd(STDOUT_FILENO, "", {SDK_EXT_INFO, "--header"},
817 CommandOptions::WithTimeout(1).Always().DropRoot().Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700818
Felipe Lemed8b94e52016-12-08 10:21:44 -0800819 printf("Kernel: ");
Felipe Lemef0292972016-11-22 13:57:05 -0800820 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
Felipe Lemed8b94e52016-12-08 10:21:44 -0800821 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
Devin Moore09fde8d2023-03-21 16:28:22 +0000822 printf("Bootconfig: ");
823 DumpFileToFd(STDOUT_FILENO, "", "/proc/bootconfig");
Felipe Leme7709f8a2017-12-05 09:30:09 -0800824 printf("Uptime: ");
825 RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"},
826 CommandOptions::WithTimeout(1).Always().Build());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800827 printf("Bugreport format version: %s\n", version_.c_str());
Kevin Jeonfa64e642023-07-27 11:36:41 -0400828 printf(
829 "Dumpstate info: id=%d pid=%d dry_run=%d parallel_run=%d strict_run=%d args=%s "
830 "bugreport_mode=%s\n",
831 id_, pid_, PropertiesHelper::IsDryRun(), PropertiesHelper::IsParallelRun(),
832 PropertiesHelper::IsStrictRun(), options_->args.c_str(),
833 options_->bugreport_mode_string.c_str());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800834 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800835}
836
Felipe Leme24b66ee2016-06-16 10:55:26 -0700837// List of file extensions that can cause a zip file attachment to be rejected by some email
838// service providers.
839static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
840 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
841 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
842 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
843};
844
Vishnu Naire97d6122018-01-18 13:58:56 -0800845status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd,
846 std::chrono::milliseconds timeout = 0ms) {
Felipe Leme24b66ee2016-06-16 10:55:26 -0700847 std::string valid_name = entry_name;
848
849 // Rename extension if necessary.
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -0700850 size_t idx = entry_name.rfind('.');
Felipe Leme24b66ee2016-06-16 10:55:26 -0700851 if (idx != std::string::npos) {
852 std::string extension = entry_name.substr(idx);
853 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
854 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
855 valid_name = entry_name + ".renamed";
856 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
857 }
858 }
859
Felipe Leme6fe9db62016-02-12 09:04:16 -0800860 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
861 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Kevin Jeon9bbe0ac2022-05-05 22:05:43 +0000862 size_t flags = ZipWriter::kCompress | ZipWriter::kDefaultCompression;
863 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), flags,
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700864 get_mtime(fd, ds.now_));
Felipe Leme1d486fe2016-10-14 18:06:47 -0700865 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700866 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700867 ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800868 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800869 }
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000870 bool finished_entry = false;
871 auto finish_entry = [this, &finished_entry] {
872 if (!finished_entry) {
873 // This should only be called when we're going to return an earlier error,
874 // which would've been logged. This may imply the file is already corrupt
875 // and any further logging from FinishEntry is more likely to mislead than
876 // not.
877 this->zip_writer_->FinishEntry();
878 }
879 };
880 auto scope_guard = android::base::make_scope_guard(finish_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -0800881 auto start = std::chrono::steady_clock::now();
882 auto end = start + timeout;
883 struct pollfd pfd = {fd, POLLIN};
Felipe Lemee82a27d2016-01-05 13:35:44 -0800884
Felipe Leme770410d2016-01-26 17:07:14 -0800885 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800886 while (1) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800887 if (timeout.count() > 0) {
888 // lambda to recalculate the timeout.
889 auto time_left_ms = [end]() {
890 auto now = std::chrono::steady_clock::now();
891 auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
892 return std::max(diff.count(), 0LL);
893 };
894
895 int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
896 if (rc < 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000897 MYLOGE("Error in poll while adding from fd to zip entry %s:%s\n",
898 entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800899 return -errno;
900 } else if (rc == 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000901 MYLOGE("Timed out adding from fd to zip entry %s:%s Timeout:%lldms\n",
Vishnu Naire97d6122018-01-18 13:58:56 -0800902 entry_name.c_str(), strerror(errno), timeout.count());
903 return TIMED_OUT;
904 }
905 }
906
Zach Riggle22200402016-08-18 01:01:24 -0400907 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800908 if (bytes_read == 0) {
909 break;
910 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800911 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800912 return -errno;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800913 }
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700914 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800915 if (err) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700916 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800917 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800918 }
919 }
920
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700921 err = zip_writer_->FinishEntry();
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000922 finished_entry = true;
Felipe Leme1d486fe2016-10-14 18:06:47 -0700923 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700924 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800925 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800926 }
927
Vishnu Naire97d6122018-01-18 13:58:56 -0800928 return OK;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800929}
930
Felipe Leme1d486fe2016-10-14 18:06:47 -0700931bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
932 android::base::unique_fd fd(
933 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700934 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800935 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800936 return false;
937 }
938
Vishnu Naire97d6122018-01-18 13:58:56 -0800939 return (AddZipEntryFromFd(entry_name, fd.get()) == OK);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800940}
941
942/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700943static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800944 return (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) == OK) ? 0 : 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800945}
946
Felipe Leme1d486fe2016-10-14 18:06:47 -0700947void Dumpstate::AddDir(const std::string& dir, bool recursive) {
Felipe Leme678727a2016-09-21 17:22:11 -0700948 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
Felipe Leme46b85da2016-11-21 17:40:45 -0800949 DurationReporter duration_reporter(dir, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700950 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800951}
952
Felipe Leme1d486fe2016-10-14 18:06:47 -0700953bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800954 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Kevin Jeon9bbe0ac2022-05-05 22:05:43 +0000955 size_t flags = ZipWriter::kCompress | ZipWriter::kDefaultCompression;
956 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), flags, ds.now_);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700957 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700958 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700959 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800960 return false;
961 }
962
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700963 err = zip_writer_->WriteBytes(content.c_str(), content.length());
Felipe Leme1d486fe2016-10-14 18:06:47 -0700964 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700965 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700966 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800967 return false;
968 }
969
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700970 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700971 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700972 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800973 return false;
974 }
975
976 return true;
977}
978
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800979static void DoKmsg() {
980 struct stat st;
981 if (!stat(PSTORE_LAST_KMSG, &st)) {
982 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
983 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
984 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
985 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
986 } else {
987 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
988 DumpFile("LAST KMSG", "/proc/last_kmsg");
989 }
990}
991
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800992static void DoKernelLogcat() {
Yao Chenbe3bbc12018-01-17 16:31:10 -0800993 unsigned long timeout_ms = logcat_timeout({"kernel"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800994 RunCommand(
995 "KERNEL LOG",
996 {"logcat", "-b", "kernel", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
997 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
998}
999
Nandana Duttdb379fa2019-10-09 16:54:41 +01001000static void DoSystemLogcat(time_t since) {
1001 char since_str[80];
1002 strftime(since_str, sizeof(since_str), "%Y-%m-%d %H:%M:%S.000", localtime(&since));
1003
1004 unsigned long timeout_ms = logcat_timeout({"main", "system", "crash"});
1005 RunCommand("SYSTEM LOG",
1006 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v", "-T",
1007 since_str},
1008 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1009}
1010
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001011static void DoRadioLogcat() {
1012 unsigned long timeout_ms = logcat_timeout({"radio"});
1013 RunCommand(
1014 "RADIO LOG",
1015 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1016 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
1017}
1018
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001019static void DoLogcat() {
Vishnu Nair6921f802017-11-22 09:17:23 -08001020 unsigned long timeout_ms;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001021 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
1022 // calculate timeout
Yao Chenbe3bbc12018-01-17 16:31:10 -08001023 timeout_ms = logcat_timeout({"main", "system", "crash"});
Tony Makae737652017-03-30 17:47:09 +01001024 RunCommand("SYSTEM LOG",
Vishnu Nair6921f802017-11-22 09:17:23 -08001025 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1026 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -08001027 timeout_ms = logcat_timeout({"events"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001028 RunCommand(
1029 "EVENT LOG",
1030 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001031 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Yao Chenbe3bbc12018-01-17 16:31:10 -08001032 timeout_ms = logcat_timeout({"stats"});
1033 RunCommand(
1034 "STATS LOG",
1035 {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001036 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001037 DoRadioLogcat();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001038
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001039 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001040 RunCommand("LAST LOGCAT", {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable",
1041 "-v", "uid", "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001042}
1043
Mike Ma5c267872019-08-21 11:31:34 -07001044static void DumpIncidentReport() {
Mike Ma5c267872019-08-21 11:31:34 -07001045 const std::string path = ds.bugreport_internal_dir_ + "/tmp_incident_report";
1046 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1047 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1048 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1049 if (fd < 0) {
1050 MYLOGE("Could not open %s to dump incident report.\n", path.c_str());
1051 return;
1052 }
Kevin Jeonfa64e642023-07-27 11:36:41 -04001053 RunCommandToFd(fd, "", {"incident", "-u"},
1054 CommandOptions::WithTimeout(PropertiesHelper::IsStrictRun() ? 20 : 120).Build());
Mike Ma5c267872019-08-21 11:31:34 -07001055 bool empty = 0 == lseek(fd, 0, SEEK_END);
1056 if (!empty) {
1057 // Use a different name from "incident.proto"
1058 // /proto/incident.proto is reserved for incident service dump
1059 // i.e. metadata for debugging.
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001060 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "incident_report" + kProtoExt,
1061 path);
1062 } else {
1063 unlink(path.c_str());
Mike Ma5c267872019-08-21 11:31:34 -07001064 }
Mike Ma5c267872019-08-21 11:31:34 -07001065}
1066
Aaron Huang24d215d2022-04-27 18:51:16 +08001067static void DumpNetstatsProto() {
1068 const std::string path = ds.bugreport_internal_dir_ + "/tmp_netstats_proto";
1069 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1070 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1071 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1072 if (fd < 0) {
1073 MYLOGE("Could not open %s to dump netstats proto.\n", path.c_str());
1074 return;
1075 }
1076 RunCommandToFd(fd, "", {"dumpsys", "netstats", "--proto"},
Kevin Jeon2fb3dd62022-09-28 18:48:55 +00001077 CommandOptions::WithTimeout(5).Build());
Aaron Huang24d215d2022-04-27 18:51:16 +08001078 bool empty = 0 == lseek(fd, 0, SEEK_END);
1079 if (!empty) {
1080 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "netstats" + kProtoExt,
1081 path);
1082 } else {
1083 unlink(path.c_str());
1084 }
1085}
1086
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001087static void MaybeAddSystemTraceToZip() {
1088 // This function copies into the .zip the system trace that was snapshotted
1089 // by the early call to MaybeSnapshotSystemTrace(), if any background
1090 // tracing was happening.
Kean Mariotti853b73a2023-07-27 12:40:30 +00001091 bool system_trace_exists = access(SYSTEM_TRACE_SNAPSHOT, F_OK) == 0;
1092 if (!system_trace_exists) {
1093 // No background trace was happening at the time MaybeSnapshotSystemTrace() was invoked.
1094 if (!PropertiesHelper::IsUserBuild()) {
1095 MYLOGI(
1096 "No system traces found. Check for previously uploaded traces by looking for "
1097 "go/trace-uuid in logcat")
1098 }
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001099 return;
1100 }
1101 ds.AddZipEntry(
1102 ZIP_ROOT_DIR + SYSTEM_TRACE_SNAPSHOT,
1103 SYSTEM_TRACE_SNAPSHOT);
1104 android::os::UnlinkAndLogOnError(SYSTEM_TRACE_SNAPSHOT);
1105}
1106
Sunny Goyal35949782019-11-19 15:54:36 -08001107static void DumpVisibleWindowViews() {
Sunny Goyal35949782019-11-19 15:54:36 -08001108 DurationReporter duration_reporter("VISIBLE WINDOW VIEWS");
1109 const std::string path = ds.bugreport_internal_dir_ + "/tmp_visible_window_views";
1110 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1111 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1112 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1113 if (fd < 0) {
1114 MYLOGE("Could not open %s to dump visible views.\n", path.c_str());
1115 return;
1116 }
1117 RunCommandToFd(fd, "", {"cmd", "window", "dump-visible-window-views"},
Kevin Jeon774abde2022-09-28 18:20:43 +00001118 CommandOptions::WithTimeout(10).Build());
Sunny Goyal35949782019-11-19 15:54:36 -08001119 bool empty = 0 == lseek(fd, 0, SEEK_END);
1120 if (!empty) {
1121 ds.AddZipEntry("visible_windows.zip", path);
1122 } else {
1123 MYLOGW("Failed to dump visible windows\n");
1124 }
1125 unlink(path.c_str());
1126}
1127
Jayachandran Ca94c7172017-06-10 15:08:12 -07001128static void DumpIpTablesAsRoot() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001129 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
1130 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +09001131 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001132 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +09001133 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
1134 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
1135 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
1136 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001137}
1138
Woody Lin20767a92022-11-29 15:50:24 +08001139static void DumpShutdownCheckpoints() {
1140 const bool shutdown_checkpoints_dumped = AddDumps(
1141 ds.shutdown_checkpoints_.begin(), ds.shutdown_checkpoints_.end(),
1142 "SHUTDOWN CHECKPOINTS", false /* add_to_zip */);
1143 if (!shutdown_checkpoints_dumped) {
1144 printf("*** NO SHUTDOWN CHECKPOINTS to dump in %s\n\n",
1145 SHUTDOWN_CHECKPOINTS_DIR.c_str());
1146 }
1147}
1148
David Andersond9ba4752018-12-11 18:26:59 -08001149static void DumpDynamicPartitionInfo() {
1150 if (!::android::base::GetBoolProperty("ro.boot.dynamic_partitions", false)) {
1151 return;
1152 }
1153
1154 RunCommand("LPDUMP", {"lpdump", "--all"});
David Anderson6650ade2019-10-02 15:18:59 -07001155 RunCommand("DEVICE-MAPPER", {"gsid", "dump-device-mapper"});
David Andersond9ba4752018-12-11 18:26:59 -08001156}
1157
Chris Morin5a50d482022-02-01 17:41:18 -08001158static void AddAnrTraceDir(const std::string& anr_traces_dir) {
Narayan Kamath8f788292017-05-25 13:20:39 +01001159 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
1160 anr_traces_dir.c_str());
1161
1162 // If we're here, dump_traces_path will always be a temporary file
1163 // (created with mkostemp or similar) that contains dumps taken earlier
1164 // on in the process.
1165 if (dump_traces_path != nullptr) {
Chris Morin5a50d482022-02-01 17:41:18 -08001166 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
1167 dump_traces_path);
1168 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
Narayan Kamath8f788292017-05-25 13:20:39 +01001169
1170 const int ret = unlink(dump_traces_path);
1171 if (ret == -1) {
1172 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
1173 strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -07001174 }
1175 }
1176
Narayan Kamathbd863722017-06-01 18:50:12 +01001177 // Add a specific message for the first ANR Dump.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001178 if (ds.anr_data_.size() > 0) {
Chris Morin5a50d482022-02-01 17:41:18 -08001179 // The "last" ANR will always be present in the body of the main entry.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001180 AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1,
Chris Morin5a50d482022-02-01 17:41:18 -08001181 "VM TRACES AT LAST ANR", false /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001182
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001183 // Historical ANRs are always included as separate entries in the bugreport zip file.
Chris Morin5a50d482022-02-01 17:41:18 -08001184 AddDumps(ds.anr_data_.begin(), ds.anr_data_.end(),
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001185 "HISTORICAL ANR", true /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001186 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +01001187 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
1188 }
1189}
1190
1191static void AddAnrTraceFiles() {
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001192 std::string anr_traces_dir = "/data/anr";
Narayan Kamath8f788292017-05-25 13:20:39 +01001193
Chris Morin5a50d482022-02-01 17:41:18 -08001194 AddAnrTraceDir(anr_traces_dir);
Narayan Kamath8f788292017-05-25 13:20:39 +01001195
Makoto Onuki83ec63f2019-01-31 17:08:59 -08001196 RunCommand("ANR FILES", {"ls", "-lt", ANR_DIR});
1197
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001198 // Slow traces for slow operations.
Felipe Lemee184f662016-10-27 10:04:47 -07001199 struct stat st;
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001200 int i = 0;
1201 while (true) {
1202 const std::string slow_trace_path =
1203 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
1204 if (stat(slow_trace_path.c_str(), &st)) {
1205 // No traces file at this index, done with the files.
1206 break;
Felipe Lemee184f662016-10-27 10:04:47 -07001207 }
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001208 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
1209 i++;
Felipe Lemee184f662016-10-27 10:04:47 -07001210 }
1211}
1212
Wei Wang509bb5d2017-06-09 14:42:12 -07001213static void DumpBlockStatFiles() {
1214 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -07001215
Wei Wang1dc1ef52017-06-12 11:28:37 -07001216 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
1217
1218 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001219 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1220 return;
1221 }
1222
1223 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -07001224 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001225 if ((d->d_name[0] == '.')
1226 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1227 || (d->d_name[1] == '\0'))) {
1228 continue;
1229 }
1230 const std::string new_path =
1231 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1232 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1233 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1234 printf("\n");
1235 }
Wei Wang1dc1ef52017-06-12 11:28:37 -07001236 return;
Wei Wang509bb5d2017-06-09 14:42:12 -07001237}
Jayachandran Ca94c7172017-06-10 15:08:12 -07001238
1239static void DumpPacketStats() {
1240 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
Jayachandran Ca94c7172017-06-10 15:08:12 -07001241}
1242
1243static void DumpIpAddrAndRules() {
1244 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
Ray Chencbf278a2023-11-20 07:49:45 +00001245 RunCommand("NETWORK INTERFACES", {"ip", "-s", "link"});
Jayachandran Ca94c7172017-06-10 15:08:12 -07001246 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1247 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1248 RunCommand("IP RULES", {"ip", "rule", "show"});
1249 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1250}
1251
Nandana Dutt5c390032019-03-12 10:52:56 +00001252static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, int priority,
1253 std::chrono::milliseconds timeout,
1254 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001255 auto start = std::chrono::steady_clock::now();
Vishnu Naire97d6122018-01-18 13:58:56 -08001256 sp<android::IServiceManager> sm = defaultServiceManager();
1257 Dumpsys dumpsys(sm.get());
Vishnu Naire97d6122018-01-18 13:58:56 -08001258 Vector<String16> args;
1259 Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
Vishnu Naire97d6122018-01-18 13:58:56 -08001260 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1261 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001262 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001263 std::string path(title);
1264 path.append(" - ").append(String8(service).c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -08001265 size_t bytes_written = 0;
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001266 if (PropertiesHelper::IsDryRun()) {
1267 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1268 dumpsys.writeDumpFooter(STDOUT_FILENO, service, std::chrono::milliseconds(1));
1269 } else {
Devin Mooref492c1a2023-03-15 19:19:03 +00001270 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP | Dumpsys::TYPE_PID |
1271 Dumpsys::TYPE_CLIENTS | Dumpsys::TYPE_THREAD,
Devin Mooreae68df22023-02-24 20:59:51 +00001272 service, args);
1273 if (status == OK) {
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001274 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1275 std::chrono::duration<double> elapsed_seconds;
1276 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH &&
1277 service == String16("meminfo")) {
1278 // Use a longer timeout for meminfo, since 30s is not always enough.
1279 status = dumpsys.writeDump(STDOUT_FILENO, service, 60s,
1280 /* as_proto = */ false, elapsed_seconds,
1281 bytes_written);
1282 } else {
1283 status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
1284 /* as_proto = */ false, elapsed_seconds,
1285 bytes_written);
1286 }
1287 dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
1288 bool dump_complete = (status == OK);
1289 dumpsys.stopDumpThread(dump_complete);
Devin Moorecdfa4602023-03-16 20:49:39 +00001290 } else {
1291 MYLOGE("Failed to start dump thread for service: %s, status: %d",
1292 String8(service).c_str(), status);
Gavin Corkeryfac7e2b2021-07-08 22:39:02 +01001293 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001294 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001295
1296 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1297 std::chrono::steady_clock::now() - start);
1298 if (elapsed_duration > timeout) {
1299 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1300 elapsed_duration.count());
1301 break;
1302 }
1303 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001304 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001305}
1306
Vishnu Nair64afc022018-02-01 15:29:34 -08001307static void RunDumpsysText(const std::string& title, int priority,
1308 std::chrono::milliseconds timeout,
1309 std::chrono::milliseconds service_timeout) {
1310 DurationReporter duration_reporter(title);
1311 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1312 fsync(STDOUT_FILENO);
1313 RunDumpsysTextByPriority(title, priority, timeout, service_timeout);
1314}
1315
1316/* Dump all services registered with Normal or Default priority. */
Nandana Dutt5c390032019-03-12 10:52:56 +00001317static Dumpstate::RunStatus RunDumpsysTextNormalPriority(const std::string& title,
1318 std::chrono::milliseconds timeout,
1319 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001320 DurationReporter duration_reporter(title);
1321 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1322 fsync(STDOUT_FILENO);
1323 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout,
1324 service_timeout);
Nandana Dutt5c390032019-03-12 10:52:56 +00001325
1326 RETURN_IF_USER_DENIED_CONSENT();
1327
1328 return RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1329 service_timeout);
Vishnu Nair64afc022018-02-01 15:29:34 -08001330}
1331
Nandana Dutt5c390032019-03-12 10:52:56 +00001332static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priority,
1333 std::chrono::milliseconds timeout,
1334 std::chrono::milliseconds service_timeout) {
Vishnu Naire97d6122018-01-18 13:58:56 -08001335 sp<android::IServiceManager> sm = defaultServiceManager();
1336 Dumpsys dumpsys(sm.get());
1337 Vector<String16> args;
1338 Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
1339 DurationReporter duration_reporter(title);
1340
1341 auto start = std::chrono::steady_clock::now();
1342 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
1343 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001344 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001345 std::string path(kProtoPath);
1346 path.append(String8(service).c_str());
1347 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
1348 path.append("_CRITICAL");
1349 } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
1350 path.append("_HIGH");
1351 }
1352 path.append(kProtoExt);
Steven Morelandcbd69fc2021-07-20 20:45:43 +00001353 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP, service, args);
Vishnu Naire97d6122018-01-18 13:58:56 -08001354 if (status == OK) {
1355 status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
1356 bool dumpTerminated = (status == OK);
1357 dumpsys.stopDumpThread(dumpTerminated);
1358 }
1359 ZipWriter::FileEntry file_entry;
1360 ds.zip_writer_->GetLastEntry(&file_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -08001361
1362 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1363 std::chrono::steady_clock::now() - start);
1364 if (elapsed_duration > timeout) {
1365 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1366 elapsed_duration.count());
1367 break;
1368 }
1369 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001370 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001371}
1372
Nandana Dutta7db6342018-11-21 14:53:34 +00001373// Runs dumpsys on services that must dump first and will take less than 100ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001374static Dumpstate::RunStatus RunDumpsysCritical() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001375 RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1376 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Nandana Dutt5c390032019-03-12 10:52:56 +00001377
1378 RETURN_IF_USER_DENIED_CONSENT();
1379
1380 return RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1381 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Vishnu Nair780b1282017-10-10 13:57:24 -07001382}
1383
1384// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001385static Dumpstate::RunStatus RunDumpsysHigh() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001386 // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
1387 // high priority. Reduce timeout once they are able to dump in a shorter time or
1388 // moved to a parallel task.
1389 RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1390 /* timeout= */ 90s, /* service_timeout= */ 30s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001391
1392 RETURN_IF_USER_DENIED_CONSENT();
1393
1394 return RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1395 /* timeout= */ 5s, /* service_timeout= */ 1s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001396}
1397
1398// Runs dumpsys on services that must dump but can take up to 10s to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001399static Dumpstate::RunStatus RunDumpsysNormal() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001400 RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001401
1402 RETURN_IF_USER_DENIED_CONSENT();
1403
1404 return RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1405 /* timeout= */ 90s, /* service_timeout= */ 10s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001406}
1407
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001408/*
1409 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1410 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1411 * if it's not running in the parallel task.
1412 */
1413static void DumpHals(int out_fd = STDOUT_FILENO) {
Yifan Hong30528a22020-08-07 18:24:06 -07001414 RunCommand("HARDWARE HALS", {"lshal", "--all", "--types=all"},
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001415 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build(),
1416 false, out_fd);
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001417
Steven Moreland44cd9482018-01-04 16:24:13 -08001418 using android::hidl::manager::V1_0::IServiceManager;
1419 using android::hardware::defaultServiceManager;
1420
1421 sp<IServiceManager> sm = defaultServiceManager();
1422 if (sm == nullptr) {
1423 MYLOGE("Could not retrieve hwservicemanager to dump hals.\n");
1424 return;
1425 }
1426
1427 auto ret = sm->list([&](const auto& interfaces) {
1428 for (const std::string& interface : interfaces) {
1429 std::string cleanName = interface;
Steven Morelandc6b1fc22023-07-26 23:53:58 +00001430 std::replace_if(
1431 cleanName.begin(), cleanName.end(),
1432 [](char c) {
1433 return !isalnum(c) && std::string("@-_.").find(c) == std::string::npos;
1434 },
1435 '_');
Nandana Dutt979388e2018-11-30 16:48:55 +00001436 const std::string path = ds.bugreport_internal_dir_ + "/lshal_debug_" + cleanName;
Steven Moreland44cd9482018-01-04 16:24:13 -08001437
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001438 bool empty = false;
Steven Moreland44cd9482018-01-04 16:24:13 -08001439 {
1440 auto fd = android::base::unique_fd(
1441 TEMP_FAILURE_RETRY(open(path.c_str(),
1442 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1443 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1444 if (fd < 0) {
1445 MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str());
1446 continue;
1447 }
1448 RunCommandToFd(fd,
1449 "",
Steven Morelandc81cd3c2018-01-18 14:36:26 -08001450 {"lshal", "debug", "-E", interface},
Steven Moreland44cd9482018-01-04 16:24:13 -08001451 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1452
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001453 empty = 0 == lseek(fd, 0, SEEK_END);
Steven Moreland44cd9482018-01-04 16:24:13 -08001454 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001455 if (!empty) {
1456 ds.EnqueueAddZipEntryAndCleanupIfNeeded("lshal-debug/" + cleanName + ".txt",
1457 path);
1458 } else {
1459 unlink(path.c_str());
1460 }
Steven Moreland44cd9482018-01-04 16:24:13 -08001461 }
1462 });
1463
1464 if (!ret.isOk()) {
1465 MYLOGE("Could not list hals from hwservicemanager.\n");
1466 }
1467}
1468
Devin Moore8df81bb2022-06-08 22:47:02 +00001469// Dump all of the files that make up the vendor interface.
1470// See the files listed in dumpFileList() for the latest list of files.
1471static void DumpVintf() {
Devin Moore16271d92022-09-22 18:28:48 +00001472
1473 const std::string sku = android::base::GetProperty("ro.boot.product.hardware.sku", "");
1474 const auto vintfFiles = android::vintf::details::dumpFileList(sku);
Devin Moore8df81bb2022-06-08 22:47:02 +00001475 for (const auto vintfFile : vintfFiles) {
1476 struct stat st;
1477 if (stat(vintfFile.c_str(), &st) == 0) {
1478 if (S_ISDIR(st.st_mode)) {
1479 ds.AddDir(vintfFile, true /* recursive */);
1480 } else {
1481 ds.EnqueueAddZipEntryAndCleanupIfNeeded(ZIP_ROOT_DIR + vintfFile,
1482 vintfFile);
1483 }
1484 }
1485 }
1486}
1487
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001488static void DumpExternalFragmentationInfo() {
1489 struct stat st;
1490 if (stat("/proc/buddyinfo", &st) != 0) {
1491 MYLOGE("Unable to dump external fragmentation info\n");
1492 return;
1493 }
1494
1495 printf("------ EXTERNAL FRAGMENTATION INFO ------\n");
1496 std::ifstream ifs("/proc/buddyinfo");
1497 auto unusable_index_regex = std::regex{"Node\\s+([0-9]+),\\s+zone\\s+(\\S+)\\s+(.*)"};
1498 for (std::string line; std::getline(ifs, line);) {
1499 std::smatch match_results;
1500 if (std::regex_match(line, match_results, unusable_index_regex)) {
1501 std::stringstream free_pages(std::string{match_results[3]});
1502 std::vector<int> free_pages_per_order(std::istream_iterator<int>{free_pages},
1503 std::istream_iterator<int>());
1504
1505 int total_free_pages = 0;
1506 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1507 total_free_pages += (free_pages_per_order[i] * std::pow(2, i));
1508 }
1509
1510 printf("Node %s, zone %8s", match_results[1].str().c_str(),
1511 match_results[2].str().c_str());
1512
1513 int usable_free_pages = total_free_pages;
1514 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1515 auto unusable_index = (total_free_pages - usable_free_pages) /
1516 static_cast<double>(total_free_pages);
1517 printf(" %5.3f", unusable_index);
1518 usable_free_pages -= (free_pages_per_order[i] * std::pow(2, i));
1519 }
1520
1521 printf("\n");
1522 }
1523 }
1524 printf("\n");
1525}
1526
mhasankd451a472020-05-26 18:02:39 -07001527static void DumpstateLimitedOnly() {
EdenSue8fe4522023-11-20 15:37:23 +08001528 // Trimmed-down version of dumpstate to only include a allowlisted
mhasankd451a472020-05-26 18:02:39 -07001529 // set of logs (system log, event log, and system server / system app
1530 // crashes, and networking logs). See b/136273873 and b/138459828
1531 // for context.
1532 DurationReporter duration_reporter("DUMPSTATE");
1533 unsigned long timeout_ms;
1534 // calculate timeout
1535 timeout_ms = logcat_timeout({"main", "system", "crash"});
1536 RunCommand("SYSTEM LOG",
1537 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1538 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1539 timeout_ms = logcat_timeout({"events"});
1540 RunCommand(
1541 "EVENT LOG",
1542 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1543 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1544
1545 printf("========================================================\n");
1546 printf("== Networking Service\n");
1547 printf("========================================================\n");
1548
1549 RunDumpsys("DUMPSYS NETWORK_SERVICE_LIMITED", {"wifi", "-a"},
1550 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hugo Benichiaa162682020-10-30 23:28:56 +09001551 RunDumpsys("DUMPSYS CONNECTIVITY REQUESTS", {"connectivity", "requests"},
1552 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
mhasankd451a472020-05-26 18:02:39 -07001553
1554 printf("========================================================\n");
1555 printf("== Dropbox crashes\n");
1556 printf("========================================================\n");
1557
1558 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1559 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1560
1561 printf("========================================================\n");
1562 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1563 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1564 printf("========================================================\n");
1565 printf("== dumpstate: done (id %d)\n", ds.id_);
1566 printf("========================================================\n");
1567}
1568
Rhed Jaoe017f982020-07-21 17:58:41 +08001569/*
1570 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1571 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1572 * if it's not running in the parallel task.
1573 */
1574static void DumpCheckins(int out_fd = STDOUT_FILENO) {
1575 dprintf(out_fd, "========================================================\n");
1576 dprintf(out_fd, "== Checkins\n");
1577 dprintf(out_fd, "========================================================\n");
1578
1579 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"}, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001580 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"}, out_fd);
1581 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"}, out_fd);
1582 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"}, out_fd);
1583 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"}, out_fd);
1584}
1585
1586/*
1587 * Runs dumpsys on activity service to dump all application activities, services
1588 * and providers in the device.
1589 *
1590 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1591 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1592 * if it's not running in the parallel task.
1593 */
1594static void DumpAppInfos(int out_fd = STDOUT_FILENO) {
1595 dprintf(out_fd, "========================================================\n");
1596 dprintf(out_fd, "== Running Application Activities\n");
1597 dprintf(out_fd, "========================================================\n");
1598
1599 // The following dumpsys internally collects output from running apps, so it can take a long
1600 // time. So let's extend the timeout.
1601
1602 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1603
1604 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1605
1606 dprintf(out_fd, "========================================================\n");
1607 dprintf(out_fd, "== Running Application Services (platform)\n");
1608 dprintf(out_fd, "========================================================\n");
1609
1610 RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
1611 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1612
1613 dprintf(out_fd, "========================================================\n");
1614 dprintf(out_fd, "== Running Application Services (non-platform)\n");
1615 dprintf(out_fd, "========================================================\n");
1616
1617 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1618 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1619
1620 dprintf(out_fd, "========================================================\n");
1621 dprintf(out_fd, "== Running Application Providers (platform)\n");
1622 dprintf(out_fd, "========================================================\n");
1623
1624 RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
Rhed Jaob049f182021-01-11 21:08:43 +08001625 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001626
1627 dprintf(out_fd, "========================================================\n");
1628 dprintf(out_fd, "== Running Application Providers (non-platform)\n");
1629 dprintf(out_fd, "========================================================\n");
1630
1631 RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1632 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1633}
1634
Nandana Dutt5c390032019-03-12 10:52:56 +00001635// Dumps various things. Returns early with status USER_CONSENT_DENIED if user denies consent
1636// via the consent they are shown. Ignores other errors that occur while running various
1637// commands. The consent checking is currently done around long running tasks, which happen to
1638// be distributed fairly evenly throughout the function.
Kean Mariotti306633e2022-09-05 16:30:47 +00001639Dumpstate::RunStatus Dumpstate::dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001640 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001641
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001642 // Enqueue slow functions into the thread pool, if the parallel run is enabled.
Aaron Huang24d215d2022-04-27 18:51:16 +08001643 std::future<std::string> dump_hals, dump_incident_report, dump_board, dump_checkins,
Kean Mariotti306633e2022-09-05 16:30:47 +00001644 dump_netstats_report, post_process_ui_traces;
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001645 if (ds.dump_pool_) {
1646 // Pool was shutdown in DumpstateDefaultAfterCritical method in order to
Kean Mariotti306633e2022-09-05 16:30:47 +00001647 // drop root user. Restarts it.
1648 ds.dump_pool_->start(/* thread_counts = */3);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001649
Chris Morinbc223142022-02-04 14:17:11 -08001650 dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
1651 dump_incident_report = ds.dump_pool_->enqueueTask(
1652 DUMP_INCIDENT_REPORT_TASK, &DumpIncidentReport);
Aaron Huang24d215d2022-04-27 18:51:16 +08001653 dump_netstats_report = ds.dump_pool_->enqueueTask(
1654 DUMP_NETSTATS_PROTO_TASK, &DumpNetstatsProto);
Chris Morinbc223142022-02-04 14:17:11 -08001655 dump_board = ds.dump_pool_->enqueueTaskWithFd(
1656 DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
1657 dump_checkins = ds.dump_pool_->enqueueTaskWithFd(DUMP_CHECKINS_TASK, &DumpCheckins, _1);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001658 }
1659
Nandana Dutt5c390032019-03-12 10:52:56 +00001660 // Dump various things. Note that anything that takes "long" (i.e. several seconds) should
1661 // check intermittently (if it's intrerruptable like a foreach on pids) and/or should be wrapped
1662 // in a consent check (via RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK).
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001663 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001664 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001665 DumpBlockStatFiles();
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001666 DumpFile("MEMORY INFO", "/proc/meminfo");
1667 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001668 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001669
Kevin Jeon947922b2022-09-21 00:29:18 +00001670 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "BUGREPORT_PROCDUMP", {"bugreport_procdump"},
1671 CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001672
Sunny Goyal35949782019-11-19 15:54:36 -08001673 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpVisibleWindowViews);
1674
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001675 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1676 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1677 DumpFile("SLAB INFO", "/proc/slabinfo");
1678 DumpFile("ZONEINFO", "/proc/zoneinfo");
1679 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1680 DumpFile("BUDDYINFO", "/proc/buddyinfo");
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001681 DumpExternalFragmentationInfo();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001682
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001683 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001684
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001685 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001686 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001687
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001688 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001689 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_hals));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001690 } else {
1691 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_HALS_TASK, DumpHals);
1692 }
Steven Moreland81b429e2017-01-31 19:50:46 -08001693
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001694 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001695 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001696 struct stat s;
1697 if (stat("/proc/modules", &s) != 0) {
1698 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1699 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001700 RunCommand("LSMOD", {"lsmod"});
Woody Linc198f252021-05-04 16:37:11 +08001701 RunCommand("MODULES INFO",
1702 {"sh", "-c", "cat /proc/modules | cut -d' ' -f1 | "
1703 " while read MOD ; do echo modinfo:$MOD ; modinfo $MOD ; "
1704 "done"}, CommandOptions::AS_ROOT);
Felipe Lemee4eca582016-06-10 17:48:08 -07001705 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001706
Tom Cherryb87dbfa2020-07-28 11:28:53 -07001707 if (android::base::GetBoolProperty("ro.logd.kernel", false)) {
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001708 DoKernelLogcat();
1709 } else {
1710 do_dmesg();
1711 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001712
Devin Moore8df81bb2022-06-08 22:47:02 +00001713 DumpVintf();
1714
Felipe Lemef0292972016-11-22 13:57:05 -08001715 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001716
Jeff Brown1dc94e32014-09-11 14:15:27 -07001717 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001718 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001719
Jack Yu5a6b2e22020-08-14 18:13:35 +08001720 /* Dump Nfc NCI logs */
1721 ds.AddDir("/data/misc/nfc/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001722
Paul Chang0d2aad72020-02-13 20:04:03 +08001723 if (ds.options_->do_screenshot && !ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001724 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001725 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001726 }
1727
Felipe Lemee184f662016-10-27 10:04:47 -07001728 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001729
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001730 MaybeAddSystemTraceToZip();
1731
Narayan Kamath8f788292017-05-25 13:20:39 +01001732 // NOTE: tombstones are always added as separate entries in the zip archive
1733 // and are not interspersed with the main report.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001734 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
Narayan Kamathbd863722017-06-01 18:50:12 +01001735 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001736 if (!tombstones_dumped) {
1737 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001738 }
1739
Jayachandran Ca94c7172017-06-10 15:08:12 -07001740 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001741
Lorenzo Colitti807f2dd2022-05-27 12:48:37 +09001742 RunDumpsys("EBPF MAP STATS", {"connectivity", "trafficcontroller"});
Chenbo Feng276a3b62018-08-07 11:44:49 -07001743
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001744 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001745
Woody Lin20767a92022-11-29 15:50:24 +08001746 DumpShutdownCheckpoints();
1747
Jayachandran Ca94c7172017-06-10 15:08:12 -07001748 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001749
1750 dump_route_tables();
1751
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001752 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1753 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1754 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001755
Nandana Dutt5c390032019-03-12 10:52:56 +00001756 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysHigh);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001757
Chiachang Wang668ede42021-05-17 17:14:20 +08001758 // The dump mechanism in connectivity is refactored due to modularization work. Connectivity can
1759 // only register with a default priority(NORMAL priority). Dumpstate has to call connectivity
1760 // dump with priority parameters to dump high priority information.
1761 RunDumpsys("SERVICE HIGH connectivity", {"connectivity", "--dump-priority", "HIGH"},
1762 CommandOptions::WithTimeout(10).Build());
1763
Elliott Hughes23ccc622017-02-28 10:14:22 -08001764 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001765
Joe Onoratod38bc3a2023-06-29 15:48:28 -07001766 DumpFile("SYSTEM BUILD-TIME RELEASE FLAGS", "/system/etc/build_flags.json");
1767 DumpFile("SYSTEM_EXT BUILD-TIME RELEASE FLAGS", "/system_ext/etc/build_flags.json");
1768 DumpFile("PRODUCT BUILD-TIME RELEASE FLAGS", "/product/etc/build_flags.json");
1769 DumpFile("VENDOR BUILD-TIME RELEASE FLAGS", "/vendor/etc/build_flags.json");
1770
Mårten Kongstad5ad813f2023-09-28 10:09:18 +02001771 RunCommand("ACONFIG FLAGS", {PRINT_FLAGS},
1772 CommandOptions::WithTimeout(10).Always().DropRoot().Build());
Joe Onoratod38bc3a2023-06-29 15:48:28 -07001773
Jin Qianf334d662017-10-10 14:41:37 -07001774 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001775
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001776 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001777
Colin Crossf45fa6b2012-03-26 12:38:26 -07001778 /* Binder state is expensive to look at as it uses a lot of memory. */
Hridya Valsaraju920ba712020-02-09 16:27:01 -08001779 std::string binder_logs_dir = access("/dev/binderfs/binder_logs", R_OK) ?
1780 "/sys/kernel/debug/binder" : "/dev/binderfs/binder_logs";
1781
1782 DumpFile("BINDER FAILED TRANSACTION LOG", binder_logs_dir + "/failed_transaction_log");
1783 DumpFile("BINDER TRANSACTION LOG", binder_logs_dir + "/transaction_log");
1784 DumpFile("BINDER TRANSACTIONS", binder_logs_dir + "/transactions");
1785 DumpFile("BINDER STATS", binder_logs_dir + "/stats");
1786 DumpFile("BINDER STATE", binder_logs_dir + "/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001787
Yifan Hongd90cc652020-02-08 16:52:02 -08001788 ds.AddDir(SNAPSHOTCTL_LOG_DIR, false);
1789
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001790 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001791 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_board));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001792 } else {
1793 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
1794 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001795
Steven Moreland7440ddb2016-12-15 16:13:39 -08001796 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001797 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1798 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001799 // su does not exist on user builds, so try running without it.
1800 // This way any implementations of vril-dump that do not require
1801 // root can run on user builds.
1802 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001803 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001804 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001805 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001806 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001807 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001808 }
1809
Felipe Lemed8b94e52016-12-08 10:21:44 -08001810 printf("========================================================\n");
1811 printf("== Android Framework Services\n");
1812 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001813
Nandana Dutt5c390032019-03-12 10:52:56 +00001814 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001815
Jack He91ff2fe2021-02-18 18:23:43 -08001816 /* Dump Bluetooth HCI logs after getting bluetooth_manager dumpsys */
1817 ds.AddDir("/data/misc/bluetooth/logs", true);
1818
Rhed Jaoe017f982020-07-21 17:58:41 +08001819 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001820 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_checkins));
Rhed Jaoe017f982020-07-21 17:58:41 +08001821 } else {
1822 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_CHECKINS_TASK, DumpCheckins);
1823 }
Dianne Hackborn02bea972013-06-26 18:59:09 -07001824
Rhed Jaoc5f7ec32020-12-22 22:11:08 +08001825 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpAppInfos);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001826
Adrian Roos8b397ab2017-04-04 16:35:44 -07001827 printf("========================================================\n");
1828 printf("== Dropbox crashes\n");
1829 printf("========================================================\n");
1830
1831 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1832 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1833
Felipe Lemed8b94e52016-12-08 10:21:44 -08001834 printf("========================================================\n");
1835 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1836 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1837 printf("========================================================\n");
1838 printf("== dumpstate: done (id %d)\n", ds.id_);
1839 printf("========================================================\n");
Bookatz38472142018-09-28 10:20:24 -07001840
1841 printf("========================================================\n");
1842 printf("== Obtaining statsd metadata\n");
1843 printf("========================================================\n");
1844 // This differs from the usual dumpsys stats, which is the stats report data.
1845 RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
Mike Ma5c267872019-08-21 11:31:34 -07001846
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +09001847 // Add linker configuration directory
1848 ds.AddDir(LINKERCONFIG_DIR, true);
1849
Li Li830179f2022-01-04 12:53:29 -08001850 /* Dump frozen cgroupfs */
1851 dump_frozen_cgroupfs();
Li Li2eedd412021-06-30 15:11:53 -07001852
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001853 if (ds.dump_pool_) {
Aaron Huang24d215d2022-04-27 18:51:16 +08001854 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_netstats_report));
1855 } else {
1856 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_NETSTATS_PROTO_TASK,
1857 DumpNetstatsProto);
1858 }
1859
1860 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001861 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_incident_report));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001862 } else {
1863 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_INCIDENT_REPORT_TASK,
1864 DumpIncidentReport);
1865 }
Mike Ma5c267872019-08-21 11:31:34 -07001866
Kean Mariotti306633e2022-09-05 16:30:47 +00001867 MaybeAddUiTracesToZip();
1868
Nandana Dutt5c390032019-03-12 10:52:56 +00001869 return Dumpstate::RunStatus::OK;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001870}
1871
Nandana Dutt5c390032019-03-12 10:52:56 +00001872/*
1873 * Dumps state for the default case; drops root after it's no longer necessary.
1874 *
1875 * Returns RunStatus::OK if everything went fine.
1876 * Returns RunStatus::ERROR if there was an error.
1877 * Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport
1878 * with the caller.
1879 */
Jichao Lie89d9c12019-11-21 19:02:51 -08001880Dumpstate::RunStatus Dumpstate::DumpstateDefaultAfterCritical() {
Nandana Duttdb379fa2019-10-09 16:54:41 +01001881 // Capture first logcat early on; useful to take a snapshot before dumpstate logs take over the
1882 // buffer.
1883 DoLogcat();
1884 // Capture timestamp after first logcat to use in next logcat
1885 time_t logcat_ts = time(nullptr);
1886
Nandana Dutt4be45d12018-09-26 15:04:23 +01001887 /* collect stack traces from Dalvik and native processes (needs root) */
Chris Morinbc223142022-02-04 14:17:11 -08001888 std::future<std::string> dump_traces;
Rhed Jao5377d792020-07-16 17:37:39 +08001889 if (dump_pool_) {
1890 RETURN_IF_USER_DENIED_CONSENT();
1891 // One thread is enough since we only need to enqueue DumpTraces here.
1892 dump_pool_->start(/* thread_counts = */1);
1893
1894 // DumpTraces takes long time, post it to the another thread in the
1895 // pool, if pool is available
Chris Morinbc223142022-02-04 14:17:11 -08001896 dump_traces = dump_pool_->enqueueTask(
1897 DUMP_TRACES_TASK, &Dumpstate::DumpTraces, &ds, &dump_traces_path);
Rhed Jao5377d792020-07-16 17:37:39 +08001898 } else {
1899 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_TRACES_TASK, ds.DumpTraces,
1900 &dump_traces_path);
1901 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001902
1903 /* Run some operations that require root. */
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001904 if (!PropertiesHelper::IsDryRun()) {
Chris Morinc2cba7a2022-02-01 17:06:50 -08001905 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX);
1906 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX);
Woody Lin20767a92022-11-29 15:50:24 +08001907 ds.shutdown_checkpoints_ = GetDumpFds(
1908 SHUTDOWN_CHECKPOINTS_DIR, SHUTDOWN_CHECKPOINTS_FILE_PREFIX);
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001909 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001910
1911 ds.AddDir(RECOVERY_DIR, true);
1912 ds.AddDir(RECOVERY_DATA_DIR, true);
1913 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
Kelvin Zhang6eaa0f92022-09-12 09:29:19 -07001914 ds.AddDir(UPDATE_ENGINE_PREF_DIR, true);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001915 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1916 if (!PropertiesHelper::IsUserBuild()) {
1917 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1918 ds.AddDir(PROFILE_DATA_DIR_REF, true);
Calin Juravlef84d3692020-04-28 15:31:12 -07001919 ds.AddZipEntry(ZIP_ROOT_DIR + PACKAGE_DEX_USE_LIST, PACKAGE_DEX_USE_LIST);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001920 }
Jerry Changa1df8a92020-01-02 16:03:39 +08001921 ds.AddDir(PREREBOOT_DATA_DIR, false);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001922 add_mountinfo();
Peter Collingbourne78aa2942023-02-15 14:50:31 -08001923 for (const char* path : {"/proc/cpuinfo", "/proc/meminfo"}) {
1924 ds.AddZipEntry(ZIP_ROOT_DIR + path, path);
1925 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001926 DumpIpTablesAsRoot();
David Andersond9ba4752018-12-11 18:26:59 -08001927 DumpDynamicPartitionInfo();
Yifan Hong3945e1b2019-10-29 12:59:23 -07001928 ds.AddDir(OTA_METADATA_DIR, true);
Jeff Sharkey9df29d52023-02-06 14:26:30 -07001929 if (!PropertiesHelper::IsUserBuild()) {
1930 // Include dropbox entry files inside ZIP, but exclude
1931 // noisy WTF and StrictMode entries
1932 dump_files("", DROPBOX_DIR, skip_wtf_strictmode, _add_file_from_fd);
1933 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001934
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001935 // Capture any IPSec policies in play. No keys are exposed here.
Nandana Dutt4be45d12018-09-26 15:04:23 +01001936 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1937
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001938 // Dump IPsec stats. No keys are exposed here.
1939 DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
1940
Nandana Dutt4be45d12018-09-26 15:04:23 +01001941 // Run ss as root so we can see socket marks.
1942 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1943
1944 // Run iotop as root to show top 100 IO threads
1945 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1946
Erick Reyese68df822019-02-11 14:46:36 -08001947 // Gather shared memory buffer info if the product implements it
Hridya Valsaraju1da80c52021-01-09 22:10:11 -08001948 RunCommand("Dmabuf dump", {"dmabuf_dump"});
1949 RunCommand("Dmabuf per-buffer/per-exporter/per-device stats", {"dmabuf_dump", "-b"});
Erick Reyese68df822019-02-11 14:46:36 -08001950
Minchan Kim22c6a1e2019-09-30 15:58:10 -07001951 DumpFile("PSI cpu", "/proc/pressure/cpu");
1952 DumpFile("PSI memory", "/proc/pressure/memory");
1953 DumpFile("PSI io", "/proc/pressure/io");
1954
Steven Moreland9379c462023-12-21 02:04:27 +00001955 ds.AddZipEntry(ZIP_ROOT_DIR + KERNEL_CONFIG, KERNEL_CONFIG);
1956
Mårten Kongstad60195a72022-09-20 14:14:20 +02001957 RunCommand("SDK EXTENSIONS", {SDK_EXT_INFO, "--dump"},
1958 CommandOptions::WithTimeout(10).Always().DropRoot().Build());
1959
Rhed Jao5377d792020-07-16 17:37:39 +08001960 if (dump_pool_) {
1961 RETURN_IF_USER_DENIED_CONSENT();
Chris Morinbc223142022-02-04 14:17:11 -08001962 WaitForTask(std::move(dump_traces));
Rhed Jao5377d792020-07-16 17:37:39 +08001963
Chris Morinbc223142022-02-04 14:17:11 -08001964 // Current running thread in the pool is the root user also. Delete
1965 // the pool and make a new one later to ensure none of threads in the pool are root.
1966 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao5377d792020-07-16 17:37:39 +08001967 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001968 if (!DropRootUser()) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001969 return Dumpstate::RunStatus::ERROR;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001970 }
1971
Nandana Dutt5c390032019-03-12 10:52:56 +00001972 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttdb379fa2019-10-09 16:54:41 +01001973 Dumpstate::RunStatus status = dumpstate();
1974 // Capture logcat since the last time we did it.
1975 DoSystemLogcat(logcat_ts);
1976 return status;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001977}
1978
Rhed Jaob5685b32020-08-14 17:19:17 +08001979// Common states for telephony and wifi which are needed to be collected before
1980// dumpstate drop the root user.
1981static void DumpstateRadioAsRoot() {
1982 DumpIpTablesAsRoot();
1983 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1984}
1985
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001986// This method collects common dumpsys for telephony and wifi. Typically, wifi
1987// reports are fine to include all information, but telephony reports on user
1988// builds need to strip some content (see DumpstateTelephonyOnly).
1989static void DumpstateRadioCommon(bool include_sensitive_info = true) {
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001990 // We need to be picky about some stuff for telephony reports on user builds.
1991 if (!include_sensitive_info) {
1992 // Only dump the radio log buffer (other buffers and dumps contain too much unrelated info).
1993 DoRadioLogcat();
1994 } else {
Rhed Jaob5685b32020-08-14 17:19:17 +08001995 // DumpHals takes long time, post it to the another thread in the pool,
1996 // if pool is available.
Chris Morinbc223142022-02-04 14:17:11 -08001997 std::future<std::string> dump_hals;
Rhed Jaob5685b32020-08-14 17:19:17 +08001998 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001999 dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
Rhed Jaob5685b32020-08-14 17:19:17 +08002000 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002001 // Contains various system properties and process startup info.
2002 do_dmesg();
2003 // Logs other than the radio buffer may contain package/component names and potential PII.
2004 DoLogcat();
2005 // Too broad for connectivity problems.
2006 DoKmsg();
Rhed Jaob5685b32020-08-14 17:19:17 +08002007 // DumpHals contains unrelated hardware info (camera, NFC, biometrics, ...).
2008 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002009 WaitForTask(std::move(dump_hals));
Rhed Jaob5685b32020-08-14 17:19:17 +08002010 } else {
2011 RUN_SLOW_FUNCTION_AND_LOG(DUMP_HALS_TASK, DumpHals);
2012 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002013 }
2014
Jayachandran Ca94c7172017-06-10 15:08:12 -07002015 DumpPacketStats();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002016 DumpIpAddrAndRules();
2017 dump_route_tables();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002018 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
2019 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08002020}
2021
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002022// We use "telephony" here for legacy reasons, though this now really means "connectivity" (cellular
2023// + wifi + networking). This method collects dumpsys for connectivity debugging only. General rules
2024// for what can be included on user builds: all reported information MUST directly relate to
2025// connectivity debugging or customer support and MUST NOT contain unrelated personally identifiable
2026// information. This information MUST NOT identify user-installed packages (UIDs are OK, package
2027// names are not), and MUST NOT contain logs of user application traffic.
2028// TODO(b/148168577) rename this and other related fields/methods to "connectivity" instead.
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08002029static void DumpstateTelephonyOnly(const std::string& calling_package) {
mukesh agrawal253dad42018-01-23 21:59:59 -08002030 DurationReporter duration_reporter("DUMPSTATE");
Jichao Lie89d9c12019-11-21 19:02:51 -08002031
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002032 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
mukesh agrawal253dad42018-01-23 21:59:59 -08002033
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002034 const bool include_sensitive_info = !PropertiesHelper::IsUserBuild();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002035
Rhed Jaob5685b32020-08-14 17:19:17 +08002036 DumpstateRadioAsRoot();
2037 if (!DropRootUser()) {
2038 return;
2039 }
2040
2041 // Starts thread pool after the root user is dropped, and two additional threads
2042 // are created for DumpHals in the DumpstateRadioCommon and DumpstateBoard.
Chris Morinbc223142022-02-04 14:17:11 -08002043 std::future<std::string> dump_board;
Rhed Jaob5685b32020-08-14 17:19:17 +08002044 if (ds.dump_pool_) {
2045 ds.dump_pool_->start(/*thread_counts =*/2);
2046
2047 // DumpstateBoard takes long time, post it to the another thread in the pool,
2048 // if pool is available.
Chris Morinbc223142022-02-04 14:17:11 -08002049 dump_board = ds.dump_pool_->enqueueTaskWithFd(
2050 DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
Rhed Jaob5685b32020-08-14 17:19:17 +08002051 }
2052
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002053 DumpstateRadioCommon(include_sensitive_info);
2054
2055 if (include_sensitive_info) {
2056 // Contains too much unrelated PII, and given the unstructured nature of sysprops, we can't
2057 // really cherrypick all of the connectivity-related ones. Apps generally have no business
2058 // reading these anyway, and there should be APIs to supply the info in a more app-friendly
2059 // way.
2060 RunCommand("SYSTEM PROPERTIES", {"getprop"});
2061 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002062
2063 printf("========================================================\n");
2064 printf("== Android Framework Services\n");
2065 printf("========================================================\n");
2066
Vishnu Nair652cc802017-11-30 15:18:30 -08002067 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2068 SEC_TO_MSEC(10));
Hunter Knepshield31cbae12021-05-11 16:23:24 -07002069 RunDumpsys("DUMPSYS", {"vcn_management"}, CommandOptions::WithTimeout(90).Build(),
2070 SEC_TO_MSEC(10));
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08002071 if (include_sensitive_info) {
2072 // Carrier apps' services will be dumped below in dumpsys activity service all-non-platform.
2073 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
2074 SEC_TO_MSEC(10));
2075 } else {
2076 // If the caller is a carrier app and has a carrier service, dump it here since we aren't
2077 // running dumpsys activity service all-non-platform below. Due to the increased output, we
2078 // give a higher timeout as well.
2079 RunDumpsys("DUMPSYS", {"carrier_config", "--requesting-package", calling_package},
2080 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(30));
2081 }
2082 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002083 RunDumpsys("DUMPSYS", {"netpolicy"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2084 RunDumpsys("DUMPSYS", {"network_management"}, CommandOptions::WithTimeout(90).Build(),
Sooraj Sasindrane8d98912018-04-20 11:31:55 -07002085 SEC_TO_MSEC(10));
Hunter Knepshield0fe51b12020-03-05 16:58:20 -08002086 RunDumpsys("DUMPSYS", {"telephony.registry"}, CommandOptions::WithTimeout(90).Build(),
2087 SEC_TO_MSEC(10));
Jack Yu773cc032023-03-16 22:43:39 -07002088 RunDumpsys("DUMPSYS", {"isub"}, CommandOptions::WithTimeout(90).Build(),
2089 SEC_TO_MSEC(10));
Grant Menke56698972023-02-24 13:11:07 -08002090 RunDumpsys("DUMPSYS", {"telecom"}, CommandOptions::WithTimeout(90).Build(),
2091 SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002092 if (include_sensitive_info) {
2093 // Contains raw IP addresses, omit from reports on user builds.
2094 RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2095 // Contains raw destination IP/MAC addresses, omit from reports on user builds.
2096 RunDumpsys("DUMPSYS", {"connmetrics"}, CommandOptions::WithTimeout(90).Build(),
2097 SEC_TO_MSEC(10));
2098 // Contains package/component names, omit from reports on user builds.
2099 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
2100 SEC_TO_MSEC(10));
2101 // Contains package names, but should be relatively simple to remove them (also contains
2102 // UIDs already), omit from reports on user builds.
2103 RunDumpsys("BATTERYSTATS", {"deviceidle"}, CommandOptions::WithTimeout(90).Build(),
2104 SEC_TO_MSEC(10));
2105 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002106
2107 printf("========================================================\n");
2108 printf("== Running Application Services\n");
2109 printf("========================================================\n");
2110
2111 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
2112
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002113 if (include_sensitive_info) {
2114 printf("========================================================\n");
2115 printf("== Running Application Services (non-platform)\n");
2116 printf("========================================================\n");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002117
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002118 // Contains package/component names and potential PII, omit from reports on user builds.
2119 // To get dumps of the active CarrierService(s) on user builds, we supply an argument to the
2120 // carrier_config dumpsys instead.
2121 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
2122 DUMPSYS_COMPONENTS_OPTIONS);
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002123
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002124 printf("========================================================\n");
2125 printf("== Checkins\n");
2126 printf("========================================================\n");
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002127
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002128 // Contains package/component names, omit from reports on user builds.
2129 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
2130 }
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002131
2132 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07002133 printf("== dumpstate: done (id %d)\n", ds.id_);
2134 printf("========================================================\n");
Rhed Jaob5685b32020-08-14 17:19:17 +08002135
2136 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002137 WaitForTask(std::move(dump_board));
Rhed Jaob5685b32020-08-14 17:19:17 +08002138 } else {
2139 RUN_SLOW_FUNCTION_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
2140 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002141}
2142
mukesh agrawal253dad42018-01-23 21:59:59 -08002143// This method collects dumpsys for wifi debugging only
2144static void DumpstateWifiOnly() {
2145 DurationReporter duration_reporter("DUMPSTATE");
2146
Rhed Jaob5685b32020-08-14 17:19:17 +08002147 DumpstateRadioAsRoot();
2148 if (!DropRootUser()) {
2149 return;
2150 }
2151
2152 // Starts thread pool after the root user is dropped. Only one additional
2153 // thread is needed for DumpHals in the DumpstateRadioCommon.
2154 if (ds.dump_pool_) {
2155 ds.dump_pool_->start(/*thread_counts =*/1);
2156 }
2157
mukesh agrawal253dad42018-01-23 21:59:59 -08002158 DumpstateRadioCommon();
2159
2160 printf("========================================================\n");
2161 printf("== Android Framework Services\n");
2162 printf("========================================================\n");
2163
2164 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2165 SEC_TO_MSEC(10));
2166 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
2167 SEC_TO_MSEC(10));
2168
2169 printf("========================================================\n");
2170 printf("== dumpstate: done (id %d)\n", ds.id_);
2171 printf("========================================================\n");
2172}
2173
Elis Elliott8e401ad2023-08-08 11:18:59 +00002174// Collects a lightweight dumpstate to be used for debugging onboarding related flows.
2175static void DumpstateOnboardingOnly() {
2176 ds.AddDir(LOGPERSIST_DATA_DIR, false);
2177}
2178
Nandana Duttcf419a72019-03-14 10:40:17 +00002179Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
Gavin Corkery789d7a52021-02-24 23:52:35 +00002180 const std::string temp_file_pattern = ds.bugreport_internal_dir_ + "/dumptrace_XXXXXX";
Nandana Duttfaafd522019-03-11 09:23:09 +00002181 const size_t buf_size = temp_file_pattern.length() + 1;
2182 std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
2183 memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
2184
2185 // Create a new, empty file to receive all trace dumps.
2186 //
2187 // TODO: This can be simplified once we remove support for the old style
2188 // dumps. We can have a file descriptor passed in to dump_traces instead
2189 // of creating a file, closing it and then reopening it again.
2190 android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
2191 if (fd < 0) {
2192 MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002193 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002194 }
2195
2196 // Nobody should have access to this temporary file except dumpstate, but we
2197 // temporarily grant 'read' to 'others' here because this file is created
2198 // when tombstoned is still running as root, but dumped after dropping. This
2199 // can go away once support for old style dumping has.
2200 const int chmod_ret = fchmod(fd, 0666);
2201 if (chmod_ret < 0) {
2202 MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002203 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002204 }
2205
2206 std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
2207 if (proc.get() == nullptr) {
2208 MYLOGE("opendir /proc failed: %s\n", strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002209 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002210 }
2211
2212 // Number of times process dumping has timed out. If we encounter too many
2213 // failures, we'll give up.
2214 int timeout_failures = 0;
2215 bool dalvik_found = false;
2216
Jayant Chowdharya0a8eb22022-05-20 03:30:09 +00002217 const std::set<int> hal_pids = get_interesting_pids();
Nandana Duttfaafd522019-03-11 09:23:09 +00002218
2219 struct dirent* d;
2220 while ((d = readdir(proc.get()))) {
Nandana Duttcf419a72019-03-14 10:40:17 +00002221 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttfaafd522019-03-11 09:23:09 +00002222 int pid = atoi(d->d_name);
2223 if (pid <= 0) {
2224 continue;
2225 }
2226
Kevin Jeond0f8a982023-04-07 14:27:11 -04002227 // Skip cached processes.
2228 if (IsCached(pid)) {
2229 // For consistency, the header and footer to this message match those
2230 // dumped by debuggerd in the success case.
2231 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
2232 dprintf(fd, "Dump skipped for cached process.\n");
2233 dprintf(fd, "---- end %d ----", pid);
2234 continue;
2235 }
2236
Nandana Duttfaafd522019-03-11 09:23:09 +00002237 const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
2238 std::string exe;
2239 if (!android::base::Readlink(link_name, &exe)) {
2240 continue;
2241 }
2242
2243 bool is_java_process;
2244 if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
2245 // Don't bother dumping backtraces for the zygote.
2246 if (IsZygote(pid)) {
2247 continue;
2248 }
2249
2250 dalvik_found = true;
2251 is_java_process = true;
2252 } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
2253 is_java_process = false;
2254 } else {
2255 // Probably a native process we don't care about, continue.
2256 continue;
2257 }
2258
2259 // If 3 backtrace dumps fail in a row, consider debuggerd dead.
2260 if (timeout_failures == 3) {
2261 dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
2262 break;
2263 }
2264
2265 const uint64_t start = Nanotime();
2266 const int ret = dump_backtrace_to_file_timeout(
Kevin Jeonb8a39362023-04-04 15:00:34 -04002267 pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace, 3, fd);
Nandana Duttfaafd522019-03-11 09:23:09 +00002268
2269 if (ret == -1) {
2270 // For consistency, the header and footer to this message match those
2271 // dumped by debuggerd in the success case.
2272 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
2273 dprintf(fd, "Dump failed, likely due to a timeout.\n");
2274 dprintf(fd, "---- end %d ----", pid);
2275 timeout_failures++;
2276 continue;
2277 }
2278
2279 // We've successfully dumped stack traces, reset the failure count
2280 // and write a summary of the elapsed time to the file and continue with the
2281 // next process.
2282 timeout_failures = 0;
2283
2284 dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
2285 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
2286 }
2287
2288 if (!dalvik_found) {
2289 MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
2290 }
2291
Nandana Duttcf419a72019-03-14 10:40:17 +00002292 *path = file_name_buf.release();
2293 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002294}
2295
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002296static dumpstate_hal_hidl::DumpstateMode GetDumpstateHalModeHidl(
2297 const Dumpstate::BugreportMode bugreport_mode) {
2298 switch (bugreport_mode) {
2299 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2300 return dumpstate_hal_hidl::DumpstateMode::FULL;
2301 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2302 return dumpstate_hal_hidl::DumpstateMode::INTERACTIVE;
2303 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2304 return dumpstate_hal_hidl::DumpstateMode::REMOTE;
2305 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2306 return dumpstate_hal_hidl::DumpstateMode::WEAR;
2307 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2308 return dumpstate_hal_hidl::DumpstateMode::CONNECTIVITY;
2309 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2310 return dumpstate_hal_hidl::DumpstateMode::WIFI;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002311 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002312 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2313 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2314 }
2315 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2316}
2317
2318static dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode GetDumpstateHalModeAidl(
2319 const Dumpstate::BugreportMode bugreport_mode) {
2320 switch (bugreport_mode) {
2321 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2322 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::FULL;
2323 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2324 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::INTERACTIVE;
2325 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2326 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::REMOTE;
2327 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2328 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WEAR;
2329 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2330 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::CONNECTIVITY;
2331 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2332 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WIFI;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002333 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002334 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2335 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2336 }
2337 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2338}
2339
2340static void DoDumpstateBoardHidl(
2341 const sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_1_0,
2342 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2343 const Dumpstate::BugreportMode bugreport_mode,
2344 const size_t timeout_sec) {
2345
2346 using ScopedNativeHandle =
2347 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
2348 ScopedNativeHandle handle(native_handle_create(static_cast<int>(dumpstate_fds.size()), 0),
2349 [](native_handle_t* handle) {
2350 // we don't close file handle's here
2351 // via native_handle_close(handle)
2352 // instead we let dumpstate_fds close the file handles when
2353 // dumpstate_fds gets destroyed
2354 native_handle_delete(handle);
2355 });
2356 if (handle == nullptr) {
2357 MYLOGE("Could not create native_handle for dumpstate HAL\n");
2358 return;
2359 }
2360
2361 for (size_t i = 0; i < dumpstate_fds.size(); i++) {
2362 handle.get()->data[i] = dumpstate_fds[i].get();
2363 }
2364
2365 // Prefer version 1.1 if available. New devices launching with R are no longer allowed to
2366 // implement just 1.0.
2367 const char* descriptor_to_kill;
2368 using DumpstateBoardTask = std::packaged_task<bool()>;
2369 DumpstateBoardTask dumpstate_board_task;
2370 sp<dumpstate_hal_hidl::IDumpstateDevice> dumpstate_hal(
2371 dumpstate_hal_hidl::IDumpstateDevice::castFrom(dumpstate_hal_1_0));
2372 if (dumpstate_hal != nullptr) {
2373 MYLOGI("Using IDumpstateDevice v1.1 HIDL HAL");
2374
2375 dumpstate_hal_hidl::DumpstateMode dumpstate_hal_mode =
2376 GetDumpstateHalModeHidl(bugreport_mode);
2377
2378 descriptor_to_kill = dumpstate_hal_hidl::IDumpstateDevice::descriptor;
2379 dumpstate_board_task =
2380 DumpstateBoardTask([timeout_sec, dumpstate_hal_mode, dumpstate_hal, &handle]() -> bool {
2381 ::android::hardware::Return<dumpstate_hal_hidl::DumpstateStatus> status =
2382 dumpstate_hal->dumpstateBoard_1_1(handle.get(), dumpstate_hal_mode,
2383 SEC_TO_MSEC(timeout_sec));
2384 if (!status.isOk()) {
2385 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2386 return false;
2387 } else if (status != dumpstate_hal_hidl::DumpstateStatus::OK) {
2388 MYLOGE("dumpstateBoard failed with DumpstateStatus::%s\n",
2389 dumpstate_hal_hidl::toString(status).c_str());
2390 return false;
2391 }
2392 return true;
2393 });
2394 } else {
2395 MYLOGI("Using IDumpstateDevice v1.0 HIDL HAL");
2396
2397 descriptor_to_kill = dumpstate_hal_hidl_1_0::IDumpstateDevice::descriptor;
2398 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal_1_0, &handle]() -> bool {
2399 ::android::hardware::Return<void> status =
2400 dumpstate_hal_1_0->dumpstateBoard(handle.get());
2401 if (!status.isOk()) {
2402 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2403 return false;
2404 }
2405 return true;
2406 });
2407 }
2408 auto result = dumpstate_board_task.get_future();
2409 std::thread(std::move(dumpstate_board_task)).detach();
2410
2411 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2412 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2413 if (!android::base::SetProperty(
2414 "ctl.interface_restart",
2415 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2416 MYLOGE("Couldn't restart dumpstate HAL\n");
2417 }
2418 }
2419 // Wait some time for init to kill dumpstate vendor HAL
2420 constexpr size_t killing_timeout_sec = 10;
2421 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2422 MYLOGE(
2423 "killing dumpstateBoard timed out after %zus, continue and "
2424 "there might be racing in content\n",
2425 killing_timeout_sec);
2426 }
2427}
2428
2429static void DoDumpstateBoardAidl(
2430 const std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal,
2431 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2432 const Dumpstate::BugreportMode bugreport_mode, const size_t timeout_sec) {
2433 MYLOGI("Using IDumpstateDevice AIDL HAL");
2434
2435 const char* descriptor_to_kill;
2436 using DumpstateBoardTask = std::packaged_task<bool()>;
2437 DumpstateBoardTask dumpstate_board_task;
2438 dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode dumpstate_hal_mode =
2439 GetDumpstateHalModeAidl(bugreport_mode);
2440
2441 descriptor_to_kill = dumpstate_hal_aidl::IDumpstateDevice::descriptor;
2442 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal, &dumpstate_fds, dumpstate_hal_mode,
2443 timeout_sec]() -> bool {
2444 auto status = dumpstate_hal->dumpstateBoard(dumpstate_fds, dumpstate_hal_mode, timeout_sec);
2445
2446 if (!status.isOk()) {
2447 MYLOGE("dumpstateBoard failed: %s\n", status.getDescription().c_str());
2448 return false;
2449 }
2450 return true;
2451 });
2452 auto result = dumpstate_board_task.get_future();
2453 std::thread(std::move(dumpstate_board_task)).detach();
2454
2455 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2456 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2457 if (!android::base::SetProperty(
2458 "ctl.interface_restart",
2459 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2460 MYLOGE("Couldn't restart dumpstate HAL\n");
2461 }
2462 }
2463 // Wait some time for init to kill dumpstate vendor HAL
2464 constexpr size_t killing_timeout_sec = 10;
2465 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2466 MYLOGE(
2467 "killing dumpstateBoard timed out after %zus, continue and "
2468 "there might be racing in content\n",
2469 killing_timeout_sec);
2470 }
2471}
2472
2473static std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> GetDumpstateBoardAidlService() {
2474 const std::string aidl_instance_name =
2475 std::string(dumpstate_hal_aidl::IDumpstateDevice::descriptor) + "/default";
2476
2477 if (!AServiceManager_isDeclared(aidl_instance_name.c_str())) {
2478 return nullptr;
2479 }
2480
2481 ndk::SpAIBinder dumpstateBinder(AServiceManager_waitForService(aidl_instance_name.c_str()));
2482
2483 return dumpstate_hal_aidl::IDumpstateDevice::fromBinder(dumpstateBinder);
2484}
2485
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002486void Dumpstate::DumpstateBoard(int out_fd) {
2487 dprintf(out_fd, "========================================================\n");
2488 dprintf(out_fd, "== Board\n");
2489 dprintf(out_fd, "========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08002490
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002491 /*
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002492 * mount debugfs for non-user builds with ro.product.debugfs_restrictions.enabled
Hridya Valsaraju51101602021-04-02 14:32:46 -07002493 * set to true and unmount it after invoking dumpstateBoard_* methods.
2494 * This is to enable debug builds to not have debugfs mounted during runtime.
2495 * It will also ensure that debugfs is only accessed by the dumpstate HAL.
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002496 */
Hridya Valsaraju51101602021-04-02 14:32:46 -07002497 auto mount_debugfs =
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002498 android::base::GetBoolProperty("ro.product.debugfs_restrictions.enabled", false);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002499 if (mount_debugfs) {
2500 RunCommand("mount debugfs", {"mount", "-t", "debugfs", "debugfs", "/sys/kernel/debug"},
2501 AS_ROOT_20);
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002502 RunCommand("chmod debugfs", {"chmod", "0755", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002503 }
2504
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002505 std::vector<std::string> paths;
2506 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07002507 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002508 paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
2509 kDumpstateBoardFiles[i].c_str()));
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002510 remover.emplace_back(android::base::make_scope_guard(
2511 std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002512 }
Jie Song9fbfad02017-06-20 16:29:42 -07002513
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002514 // get dumpstate HAL AIDL implementation
2515 std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal_handle_aidl(
2516 GetDumpstateBoardAidlService());
2517 if (dumpstate_hal_handle_aidl == nullptr) {
2518 MYLOGI("No IDumpstateDevice AIDL implementation\n");
2519 }
2520
2521 // get dumpstate HAL HIDL implementation, only if AIDL HAL implementation not found
2522 sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_handle_hidl_1_0 = nullptr;
2523 if (dumpstate_hal_handle_aidl == nullptr) {
2524 dumpstate_hal_handle_hidl_1_0 = dumpstate_hal_hidl_1_0::IDumpstateDevice::getService();
2525 if (dumpstate_hal_handle_hidl_1_0 == nullptr) {
2526 MYLOGI("No IDumpstateDevice HIDL implementation\n");
2527 }
2528 }
2529
2530 // if neither HIDL nor AIDL implementation found, then return
2531 if (dumpstate_hal_handle_hidl_1_0 == nullptr && dumpstate_hal_handle_aidl == nullptr) {
2532 MYLOGE("Could not find IDumpstateDevice implementation\n");
Wei Wang587eac92018-04-05 12:17:20 -07002533 return;
2534 }
2535
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002536 // this is used to hold the file descriptors and when this variable goes out of scope
2537 // the file descriptors are closed
2538 std::vector<::ndk::ScopedFileDescriptor> dumpstate_fds;
Wei Wang587eac92018-04-05 12:17:20 -07002539
Nandana Dutt5c390032019-03-12 10:52:56 +00002540 // TODO(128270426): Check for consent in between?
Wei Wang587eac92018-04-05 12:17:20 -07002541 for (size_t i = 0; i < paths.size(); i++) {
2542 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
2543
2544 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
2545 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
2546 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
2547 if (fd < 0) {
2548 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
2549 return;
2550 }
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002551
2552 dumpstate_fds.emplace_back(fd.release());
2553 // we call fd.release() here to make sure "fd" does not get closed
2554 // after "fd" goes out of scope after this block.
2555 // "fd" will be closed when "dumpstate_fds" goes out of scope
2556 // i.e. when we exit this function
Wei Wang587eac92018-04-05 12:17:20 -07002557 }
2558
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002559 // Given that bugreport is required to diagnose failures, it's better to set an arbitrary amount
2560 // of timeout for IDumpstateDevice than to block the rest of bugreport. In the timeout case, we
2561 // will kill the HAL and grab whatever it dumped in time.
Michael Eastwood8523ea02022-03-10 16:33:08 -08002562 constexpr size_t timeout_sec = 45;
Wei Wang587eac92018-04-05 12:17:20 -07002563
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002564 if (dumpstate_hal_handle_aidl != nullptr) {
2565 DoDumpstateBoardAidl(dumpstate_hal_handle_aidl, dumpstate_fds, options_->bugreport_mode,
2566 timeout_sec);
2567 } else if (dumpstate_hal_handle_hidl_1_0 != nullptr) {
2568 // run HIDL HAL only if AIDL HAL not found
2569 DoDumpstateBoardHidl(dumpstate_hal_handle_hidl_1_0, dumpstate_fds, options_->bugreport_mode,
2570 timeout_sec);
Wei Wang587eac92018-04-05 12:17:20 -07002571 }
2572
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002573 if (mount_debugfs) {
Hridya Valsaraju51101602021-04-02 14:32:46 -07002574 auto keep_debugfs_mounted =
2575 android::base::GetProperty("persist.dbg.keep_debugfs_mounted", "");
2576 if (keep_debugfs_mounted.empty())
2577 RunCommand("unmount debugfs", {"umount", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002578 }
2579
Wei Wang587eac92018-04-05 12:17:20 -07002580 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
2581 for (size_t i = 0; i < paths.size(); i++) {
2582 struct stat s;
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002583 if (fstat(dumpstate_fds[i].get(), &s) == -1) {
2584 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(), strerror(errno));
Wei Wang587eac92018-04-05 12:17:20 -07002585 file_sizes[i] = -1;
2586 continue;
2587 }
2588 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002589 }
2590
2591 for (size_t i = 0; i < paths.size(); i++) {
2592 if (file_sizes[i] == -1) {
2593 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002594 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002595 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07002596 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002597 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002598 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002599 remover[i].Disable();
2600 EnqueueAddZipEntryAndCleanupIfNeeded(kDumpstateBoardFiles[i], paths[i]);
2601 dprintf(out_fd, "*** See %s entry ***\n", kDumpstateBoardFiles[i].c_str());
Jie Song9fbfad02017-06-20 16:29:42 -07002602 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08002603}
2604
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002605static void ShowUsage() {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002606 fprintf(stderr,
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002607 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o directory] [-p] "
2608 "[-s] [-S] [-q] [-P] [-R] [-L] [-V version]\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002609 " -h: display this help message\n"
2610 " -b: play sound file instead of vibrate, at beginning of job\n"
2611 " -e: play sound file instead of vibrate, at end of job\n"
mhasank2d75c442020-06-11 15:05:25 -07002612 " -o: write to custom directory (only in limited mode)\n"
Abhijeet Kaurbb55a3b2019-06-13 18:07:25 +01002613 " -p: capture screenshot to filename.png\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002614 " -s: write zipped file to control socket (for init)\n"
2615 " -S: write file location to control socket (for init)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002616 " -q: disable vibrate\n"
Abhijeet Kaure370d682019-10-01 16:49:30 +01002617 " -P: send broadcast when started and do progress updates\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002618 " -R: take bugreport in remote mode (shouldn't be used with -P)\n"
Nandana Dutt235864b2019-01-22 12:10:16 +00002619 " -w: start binder service and make it wait for a call to startBugreport\n"
mhasankd451a472020-05-26 18:02:39 -07002620 " -L: output limited information that is safe for submission in feedback reports\n"
Felipe Lemed071c682016-10-20 16:48:00 -07002621 " -v: prints the dumpstate header and exit\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002622}
2623
Wei Liuf87959e2016-08-26 14:51:42 -07002624static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07002625 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07002626}
2627
Felipe Leme1d486fe2016-10-14 18:06:47 -07002628bool Dumpstate::FinishZipFile() {
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002629 // Runs all enqueued adding zip entry and cleanup tasks before finishing the zip file.
2630 if (zip_entry_tasks_) {
2631 zip_entry_tasks_->run(/* do_cancel = */false);
2632 }
2633
Felipe Leme9a523ae2016-10-20 15:10:33 -07002634 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07002635 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07002636 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002637 // Final timestamp
2638 char date[80];
2639 time_t the_real_now_please_stand_up = time(nullptr);
2640 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002641 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002642 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002643
Felipe Leme9a523ae2016-10-20 15:10:33 -07002644 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002645 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08002646 return false;
2647 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07002648 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002649 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08002650 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08002651 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08002652
Felipe Leme0f3fb202016-06-10 17:10:53 -07002653 // Add log file (which contains stderr output) to zip...
2654 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002655 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07002656 MYLOGE("Failed to add dumpstate log to .zip file\n");
2657 return false;
2658 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002659 // TODO: Should truncate the existing file.
2660 // ... and re-open it for further logging.
Nandana Dutta344cb62019-02-22 15:12:35 +00002661 if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
2662 return false;
2663 }
Felipe Leme0f3fb202016-06-10 17:10:53 -07002664 fprintf(stderr, "\n");
2665
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002666 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07002667 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002668 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002669 return false;
2670 }
2671
Felipe Leme1d486fe2016-10-14 18:06:47 -07002672 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
2673 ds.zip_file.reset(nullptr);
2674
Felipe Lemee9d2c542016-11-15 11:48:26 -08002675 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002676 android::os::UnlinkAndLogOnError(tmp_path_);
Felipe Lemec4eee562016-04-21 15:42:55 -07002677
Felipe Leme1e9edc62015-12-21 16:02:13 -08002678 return true;
2679}
Felipe Leme6e01fa62015-11-11 19:35:14 -08002680
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00002681static void SendBroadcast(const std::string& action,
2682 const std::vector<std::string>& args,
2683 int32_t user_id) {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002684 // clang-format off
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00002685 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user",
2686 std::to_string(user_id), "--receiver-foreground",
2687 "--receiver-include-background", "-a", action};
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002688 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08002689
2690 am.insert(am.end(), args.begin(), args.end());
2691
Felipe Leme8d2410e2017-02-08 09:46:08 -08002692 RunCommand("", am,
2693 CommandOptions::WithTimeout(20)
2694 .Log("Sending broadcast: '%s'\n")
2695 .Always()
2696 .DropRoot()
2697 .RedirectStderr()
2698 .Build());
2699}
2700
Felipe Leme35b8cf12017-02-10 15:47:29 -08002701static void Vibrate(int duration_ms) {
2702 // clang-format off
Lais Andrade51156962021-02-22 19:21:35 +00002703 std::vector<std::string> args = {"cmd", "vibrator_manager", "synced", "-f", "-d", "dumpstate",
2704 "oneshot", std::to_string(duration_ms)};
2705 RunCommand("", args,
Felipe Leme35b8cf12017-02-10 15:47:29 -08002706 CommandOptions::WithTimeout(10)
2707 .Log("Vibrate: '%s'\n")
2708 .Always()
2709 .Build());
2710 // clang-format on
2711}
2712
Nandana Dutt979388e2018-11-30 16:48:55 +00002713static void MaybeResolveSymlink(std::string* path) {
2714 std::string resolved_path;
2715 if (android::base::Readlink(*path, &resolved_path)) {
2716 *path = resolved_path;
2717 }
2718}
2719
Nandana Dutt4be45d12018-09-26 15:04:23 +01002720/*
2721 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002722 * and adds the version file. Return false if zip_file could not be open to write.
Nandana Dutt4be45d12018-09-26 15:04:23 +01002723 */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002724static bool PrepareToWriteToFile() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002725 MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2726
Nandana Dutt4be45d12018-09-26 15:04:23 +01002727 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2728 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002729 ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002730 char date[80];
2731 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2732 ds.name_ = date;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002733
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002734 if (ds.options_->telephony_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002735 ds.base_name_ += "-telephony";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002736 } else if (ds.options_->wifi_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002737 ds.base_name_ += "-wifi";
2738 }
2739
Paul Chang0d2aad72020-02-13 20:04:03 +08002740 if (ds.options_->do_screenshot) {
Nandana Dutt9d17b942020-03-26 10:02:59 +00002741 ds.screenshot_path_ = ds.GetPath(ds.CalledByApi() ? "-png.tmp" : ".png");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002742 }
2743 ds.tmp_path_ = ds.GetPath(".tmp");
2744 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2745
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01002746 std::string destination = ds.CalledByApi()
Nandana Dutt54dbd672019-01-11 12:58:05 +00002747 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
Nandana Dutt9a76d202019-01-21 15:56:48 +00002748 : ds.bugreport_internal_dir_.c_str();
Nandana Dutt4be45d12018-09-26 15:04:23 +01002749 MYLOGD(
Nandana Dutt235c6672019-11-14 15:22:32 +00002750 "Bugreport dir: [%s] "
2751 "Base name: [%s] "
2752 "Suffix: [%s] "
2753 "Log path: [%s] "
2754 "Temporary path: [%s] "
2755 "Screenshot path: [%s]\n",
Nandana Dutt9a76d202019-01-21 15:56:48 +00002756 destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2757 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002758
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002759 ds.path_ = ds.GetPath(ds.CalledByApi() ? "-zip.tmp" : ".zip");
2760 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2761 create_parent_dirs(ds.path_.c_str());
2762 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2763 if (ds.zip_file == nullptr) {
2764 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2765 return false;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002766 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002767 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2768 ds.AddTextZipEntry("version.txt", ds.version_);
2769 return true;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002770}
2771
2772/*
Abhijeet Kaure370d682019-10-01 16:49:30 +01002773 * Finalizes writing to the file by zipping the tmp file to the final location,
Nandana Dutt4be45d12018-09-26 15:04:23 +01002774 * printing zipped file status, etc.
2775 */
2776static void FinalizeFile() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002777 bool do_text_file = !ds.FinishZipFile();
2778 if (do_text_file) {
2779 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002780 }
mhasank2d75c442020-06-11 15:05:25 -07002781
2782 std::string final_path = ds.path_;
2783 if (ds.options_->OutputToCustomFile()) {
mhasank3a4cfb42020-06-15 18:06:43 -07002784 final_path = ds.GetPath(ds.options_->out_dir, ".zip");
mhasank2d75c442020-06-11 15:05:25 -07002785 android::os::CopyFileToFile(ds.path_, final_path);
2786 }
2787
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002788 if (ds.options_->stream_to_socket) {
2789 android::os::CopyFileToFd(ds.path_, ds.control_socket_fd_);
2790 } else if (ds.options_->progress_updates_to_socket) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002791 if (do_text_file) {
2792 dprintf(ds.control_socket_fd_,
2793 "FAIL:could not create zip file, check %s "
2794 "for more details\n",
2795 ds.log_path_.c_str());
2796 } else {
mhasank2d75c442020-06-11 15:05:25 -07002797 dprintf(ds.control_socket_fd_, "OK:%s\n", final_path.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002798 }
2799 }
2800}
2801
Nandana Dutt4be45d12018-09-26 15:04:23 +01002802
Nandana Dutt58d72e22018-11-16 10:30:48 +00002803static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2804 switch (mode) {
2805 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2806 return "BUGREPORT_FULL";
2807 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2808 return "BUGREPORT_INTERACTIVE";
2809 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2810 return "BUGREPORT_REMOTE";
2811 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2812 return "BUGREPORT_WEAR";
2813 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2814 return "BUGREPORT_TELEPHONY";
2815 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2816 return "BUGREPORT_WIFI";
Elis Elliott8e401ad2023-08-08 11:18:59 +00002817 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
2818 return "BUGREPORT_ONBOARDING";
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002819 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2820 return "BUGREPORT_DEFAULT";
Nandana Dutt58d72e22018-11-16 10:30:48 +00002821 }
2822}
2823
Steven Leeb573eb82022-11-29 22:31:35 +08002824static bool IsConsentlessBugreportAllowed(const Dumpstate::DumpOptions& options) {
2825 // only BUGREPORT_TELEPHONY does not allow using consentless bugreport
2826 return !options.telephony_only;
2827}
2828
Paul Changf59c2b72020-03-10 02:08:55 +08002829static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options,
2830 bool is_screenshot_requested) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002831 // Modify com.android.shell.BugreportProgressService#isDefaultScreenshotRequired as well for
2832 // default system screenshots.
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002833 options->bugreport_mode = mode;
2834 options->bugreport_mode_string = ModeToString(mode);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002835 switch (mode) {
2836 case Dumpstate::BugreportMode::BUGREPORT_FULL:
Paul Changf59c2b72020-03-10 02:08:55 +08002837 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002838 break;
2839 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002840 // Currently, the dumpstate binder is only used by Shell to update progress.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002841 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002842 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002843 break;
2844 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002845 options->do_vibrate = false;
2846 options->is_remote_mode = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002847 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002848 break;
2849 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
Robert Ginda55ecebd2023-04-03 22:53:13 +00002850 options->do_vibrate = false;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002851 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002852 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002853 break;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002854 // TODO(b/148168577) rename TELEPHONY everywhere to CONNECTIVITY.
Nandana Dutt58d72e22018-11-16 10:30:48 +00002855 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002856 options->telephony_only = true;
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002857 options->do_progress_updates = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002858 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002859 break;
2860 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002861 options->wifi_only = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002862 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002863 break;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002864 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
2865 options->onboarding_only = true;
2866 options->do_screenshot = false;
2867 break;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002868 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2869 break;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002870 }
2871}
2872
Nandana Dutt58d72e22018-11-16 10:30:48 +00002873static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
Nandana Dutt235c6672019-11-14 15:22:32 +00002874 MYLOGI(
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002875 "do_vibrate: %d stream_to_socket: %d progress_updates_to_socket: %d do_screenshot: %d "
Rhed Jao25f50e02020-08-20 00:10:32 +08002876 "is_remote_mode: %d show_header_only: %d telephony_only: %d "
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002877 "wifi_only: %d do_progress_updates: %d fd: %d bugreport_mode: %s "
mhasankd451a472020-05-26 18:02:39 -07002878 "limited_only: %d args: %s\n",
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002879 options.do_vibrate, options.stream_to_socket, options.progress_updates_to_socket,
Paul Chang0d2aad72020-02-13 20:04:03 +08002880 options.do_screenshot, options.is_remote_mode, options.show_header_only,
Rhed Jao25f50e02020-08-20 00:10:32 +08002881 options.telephony_only, options.wifi_only,
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002882 options.do_progress_updates, options.bugreport_fd.get(),
2883 options.bugreport_mode_string.c_str(),
2884 options.limited_only, options.args.c_str());
Nandana Dutt58d72e22018-11-16 10:30:48 +00002885}
2886
Nandana Dutt54dbd672019-01-11 12:58:05 +00002887void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
Kean Mariotti306633e2022-09-05 16:30:47 +00002888 int bugreport_flags,
Nandana Dutt54dbd672019-01-11 12:58:05 +00002889 const android::base::unique_fd& bugreport_fd_in,
Paul Changf59c2b72020-03-10 02:08:55 +08002890 const android::base::unique_fd& screenshot_fd_in,
2891 bool is_screenshot_requested) {
Kean Mariotti306633e2022-09-05 16:30:47 +00002892 this->use_predumped_ui_data = bugreport_flags & BugreportFlag::BUGREPORT_USE_PREDUMPED_UI_DATA;
Gavin Corkerya44686c2022-11-23 18:16:51 +00002893 this->is_consent_deferred = bugreport_flags & BugreportFlag::BUGREPORT_FLAG_DEFER_CONSENT;
Nandana Dutt54dbd672019-01-11 12:58:05 +00002894 // Duplicate the fds because the passed in fds don't outlive the binder transaction.
Todd Frederick621533f2022-03-26 02:54:17 +00002895 bugreport_fd.reset(fcntl(bugreport_fd_in.get(), F_DUPFD_CLOEXEC, 0));
2896 screenshot_fd.reset(fcntl(screenshot_fd_in.get(), F_DUPFD_CLOEXEC, 0));
Nandana Dutt58d72e22018-11-16 10:30:48 +00002897
Paul Changf59c2b72020-03-10 02:08:55 +08002898 SetOptionsFromMode(bugreport_mode, this, is_screenshot_requested);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002899}
2900
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002901Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
2902 RunStatus status = RunStatus::OK;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002903 int c;
mhasankd451a472020-05-26 18:02:39 -07002904 while ((c = getopt(argc, argv, "dho:svqzpLPBRSV:w")) != -1) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002905 switch (c) {
2906 // clang-format off
mhasank3a4cfb42020-06-15 18:06:43 -07002907 case 'o': out_dir = optarg; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002908 case 's': stream_to_socket = true; break;
2909 case 'S': progress_updates_to_socket = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002910 case 'v': show_header_only = true; break;
2911 case 'q': do_vibrate = false; break;
Paul Chang0d2aad72020-02-13 20:04:03 +08002912 case 'p': do_screenshot = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002913 case 'P': do_progress_updates = true; break;
2914 case 'R': is_remote_mode = true; break;
mhasankd451a472020-05-26 18:02:39 -07002915 case 'L': limited_only = true; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002916 case 'V':
2917 case 'd':
2918 case 'z':
2919 // compatibility no-op
2920 break;
Nandana Dutt235864b2019-01-22 12:10:16 +00002921 case 'w':
2922 // This was already processed
2923 break;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002924 case 'h':
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002925 status = RunStatus::HELP;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002926 break;
2927 default:
2928 fprintf(stderr, "Invalid option: %c\n", c);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002929 status = RunStatus::INVALID_INPUT;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002930 break;
2931 // clang-format on
2932 }
2933 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08002934
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002935 for (int i = 0; i < argc; i++) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002936 args += argv[i];
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002937 if (i < argc - 1) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002938 args += " ";
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002939 }
2940 }
2941
2942 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
2943 optind = 1;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002944
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002945 return status;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002946}
2947
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002948bool Dumpstate::DumpOptions::ValidateOptions() const {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002949 if (bugreport_fd.get() != -1 && stream_to_socket) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002950 return false;
2951 }
2952
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002953 if ((progress_updates_to_socket || do_progress_updates) && stream_to_socket) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002954 return false;
2955 }
2956
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002957 if (is_remote_mode && (do_progress_updates || stream_to_socket)) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002958 return false;
2959 }
2960 return true;
2961}
2962
Nandana Dutt197661d2018-11-16 16:40:21 +00002963void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
2964 options_ = std::move(options);
2965}
2966
Abhijeet Kaura407fb82020-03-27 12:51:12 +00002967void Dumpstate::Initialize() {
2968 /* gets the sequential id */
2969 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
2970 id_ = ++last_id;
2971 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
2972}
2973
Nandana Duttd2f5f082019-01-18 17:13:52 +00002974Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
2975 Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
Gavin Corkerya44686c2022-11-23 18:16:51 +00002976 HandleRunStatus(status);
2977 return status;
2978}
2979
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00002980Dumpstate::RunStatus Dumpstate::Retrieve(int32_t calling_uid, const std::string& calling_package,
2981 const bool keep_bugreport_on_retrieval) {
2982 Dumpstate::RunStatus status = RetrieveInternal(calling_uid, calling_package,
2983 keep_bugreport_on_retrieval);
Gavin Corkerya44686c2022-11-23 18:16:51 +00002984 HandleRunStatus(status);
2985 return status;
2986}
2987
2988Dumpstate::RunStatus Dumpstate::RetrieveInternal(int32_t calling_uid,
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00002989 const std::string& calling_package,
2990 const bool keep_bugreport_on_retrieval) {
Gavin Corkerya44686c2022-11-23 18:16:51 +00002991 consent_callback_ = new ConsentCallback();
2992 const String16 incidentcompanion("incidentcompanion");
2993 sp<android::IBinder> ics(
2994 defaultServiceManager()->checkService(incidentcompanion));
2995 android::String16 package(calling_package.c_str());
2996 if (ics != nullptr) {
2997 MYLOGD("Checking user consent via incidentcompanion service\n");
2998 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
2999 calling_uid, package, String16(), String16(),
3000 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
3001 } else {
3002 MYLOGD(
3003 "Unable to check user consent; incidentcompanion service unavailable\n");
3004 return RunStatus::USER_CONSENT_TIMED_OUT;
3005 }
3006 UserConsentResult consent_result = consent_callback_->getResult();
3007 int timeout_ms = 30 * 1000;
3008 while (consent_result == UserConsentResult::UNAVAILABLE &&
3009 consent_callback_->getElapsedTimeMs() < timeout_ms) {
3010 sleep(1);
3011 consent_result = consent_callback_->getResult();
3012 }
3013 if (consent_result == UserConsentResult::DENIED) {
3014 return RunStatus::USER_CONSENT_DENIED;
3015 }
3016 if (consent_result == UserConsentResult::UNAVAILABLE) {
3017 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3018 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3019 consent_callback_.get());
3020 return RunStatus::USER_CONSENT_TIMED_OUT;
3021 }
3022
3023 bool copy_succeeded =
3024 android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003025
3026 if (copy_succeeded && (!android::app::admin::flags::onboarding_bugreport_v2_enabled()
3027 || !keep_bugreport_on_retrieval)) {
3028 android::os::UnlinkAndLogOnError(path_);
Gavin Corkerya44686c2022-11-23 18:16:51 +00003029 }
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003030
Gavin Corkerya44686c2022-11-23 18:16:51 +00003031 return copy_succeeded ? Dumpstate::RunStatus::OK
3032 : Dumpstate::RunStatus::ERROR;
3033}
3034
3035void Dumpstate::HandleRunStatus(Dumpstate::RunStatus status) {
3036 if (listener_ != nullptr) {
Nandana Duttbabf6c72019-01-15 14:11:12 +00003037 switch (status) {
3038 case Dumpstate::RunStatus::OK:
Gavin Corkerya44686c2022-11-23 18:16:51 +00003039 listener_->onFinished(path_.c_str());
Nandana Duttbabf6c72019-01-15 14:11:12 +00003040 break;
3041 case Dumpstate::RunStatus::HELP:
3042 break;
3043 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003044 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00003045 break;
3046 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003047 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
3048 break;
3049 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3050 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
3051 break;
3052 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
3053 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00003054 break;
3055 }
3056 }
Nandana Duttbabf6c72019-01-15 14:11:12 +00003057}
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003058void Dumpstate::Cancel() {
3059 CleanupTmpFiles();
3060 android::os::UnlinkAndLogOnError(log_path_);
3061 for (int i = 0; i < NUM_OF_DUMPS; i++) {
3062 android::os::UnlinkAndLogOnError(ds.bugreport_internal_dir_ + "/" +
3063 kDumpstateBoardFiles[i]);
3064 }
3065 tombstone_data_.clear();
3066 anr_data_.clear();
Woody Lin20767a92022-11-29 15:50:24 +08003067 shutdown_checkpoints_.clear();
Rhed Jao0daac912020-08-21 14:48:20 +08003068
3069 // Instead of shutdown the pool, we delete temporary files directly since
3070 // shutdown blocking the call.
3071 if (dump_pool_) {
3072 dump_pool_->deleteTempFiles();
3073 }
3074 if (zip_entry_tasks_) {
3075 zip_entry_tasks_->run(/*do_cancel =*/ true);
3076 }
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003077}
3078
Kean Mariotti306633e2022-09-05 16:30:47 +00003079void Dumpstate::PreDumpUiData() {
Kean Mariotti853b73a2023-07-27 12:40:30 +00003080 MaybeSnapshotSystemTrace();
Kean Mariotti306633e2022-09-05 16:30:47 +00003081 MaybeSnapshotUiTraces();
3082}
3083
Nandana Dutt979388e2018-11-30 16:48:55 +00003084/*
3085 * Dumps relevant information to a bugreport based on the given options.
3086 *
3087 * The bugreport can be dumped to a file or streamed to a socket.
3088 *
3089 * How dumping to file works:
3090 * stdout is redirected to a temporary file. This will later become the main bugreport entry.
3091 * stderr is redirected a log file.
3092 *
3093 * The temporary bugreport is then populated via printfs, dumping contents of files and
3094 * output of commands to stdout.
3095 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003096 * A bunch of other files and dumps are added to the zip archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00003097 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003098 * The temporary bugreport file and the log file also get added to the archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00003099 *
mhasank2d75c442020-06-11 15:05:25 -07003100 * Bugreports are first generated in a local directory and later copied to the caller's fd
3101 * or directory if supplied.
Nandana Dutt979388e2018-11-30 16:48:55 +00003102 */
Nandana Duttd2f5f082019-01-18 17:13:52 +00003103Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
3104 const std::string& calling_package) {
Rhed Jao5377d792020-07-16 17:37:39 +08003105 DurationReporter duration_reporter("RUN INTERNAL", /* logcat_only = */true);
Nandana Dutt979388e2018-11-30 16:48:55 +00003106 LogDumpOptions(*options_);
Nandana Dutt197661d2018-11-16 16:40:21 +00003107 if (!options_->ValidateOptions()) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00003108 MYLOGE("Invalid options specified\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003109 return RunStatus::INVALID_INPUT;
3110 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003111 /* set as high priority, and protect from OOM killer */
3112 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003113
Felipe Lemed071c682016-10-20 16:48:00 -07003114 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07003115 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003116 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003117 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003118 } else {
3119 /* fallback to kernels <= 2.6.35 */
3120 oom_adj = fopen("/proc/self/oom_adj", "we");
3121 if (oom_adj) {
3122 fputs("-17", oom_adj);
3123 fclose(oom_adj);
3124 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003125 }
3126
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003127 if (version_ == VERSION_DEFAULT) {
3128 version_ = VERSION_CURRENT;
Michal Karpinski4db754f2015-12-11 18:04:32 +00003129 }
3130
Chris Morin5a50d482022-02-01 17:41:18 -08003131 if (version_ != VERSION_CURRENT) {
3132 MYLOGE("invalid version requested ('%s'); supported values are: ('%s', '%s')\n",
3133 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003134 return RunStatus::INVALID_INPUT;
Felipe Lemed071c682016-10-20 16:48:00 -07003135 }
3136
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003137 if (options_->show_header_only) {
3138 PrintHeader();
3139 return RunStatus::OK;
Felipe Lemed071c682016-10-20 16:48:00 -07003140 }
3141
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003142 MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n",
3143 calling_uid, calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003144
Felipe Leme7447d7c2016-11-03 18:12:22 -07003145 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003146 std::string stats_path =
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003147 android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003148 progress_.reset(new Progress(stats_path));
Felipe Leme7447d7c2016-11-03 18:12:22 -07003149
Sahana Raof35ed432019-07-12 10:47:52 +01003150 if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
3151 MYLOGE("Failed to acquire wake lock: %s\n", strerror(errno));
3152 } else {
3153 // Wake lock will be released automatically on process death
3154 MYLOGD("Wake lock acquired.\n");
3155 }
3156
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08003157 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07003158
Felipe Lemef0292972016-11-22 13:57:05 -08003159 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07003160 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
3161 }
3162
Kevin Jeonfa64e642023-07-27 11:36:41 -04003163 if (PropertiesHelper::IsStrictRun()) {
3164 MYLOGI(
3165 "Running on strict-run mode, which has shorter timeouts "
3166 "(to disable, call 'setprop dumpstate.strict_run false')\n");
3167 }
3168
Nandana Dutt235c6672019-11-14 15:22:32 +00003169 MYLOGI("dumpstate info: id=%d, args='%s', bugreport_mode= %s bugreport format version: %s\n",
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00003170 id_, options_->args.c_str(), options_->bugreport_mode_string.c_str(), version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08003171
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003172 do_early_screenshot_ = options_->do_progress_updates;
Felipe Lemee338bf62015-12-07 14:03:50 -08003173
Christopher Ferrised9354f2014-10-01 17:35:01 -07003174 // If we are going to use a socket, do it as early as possible
3175 // to avoid timeouts from bugreport.
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003176 if (options_->stream_to_socket || options_->progress_updates_to_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07003177 MYLOGD("Opening control socket\n");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003178 control_socket_fd_ = open_socket_fn_("dumpstate");
Nandana Dutta344cb62019-02-22 15:12:35 +00003179 if (control_socket_fd_ == -1) {
3180 return ERROR;
3181 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003182 if (options_->progress_updates_to_socket) {
3183 options_->do_progress_updates = 1;
3184 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07003185 }
3186
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003187 if (!PrepareToWriteToFile()) {
3188 return ERROR;
3189 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08003190
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003191 // Interactive, wear & telephony modes are default to true.
3192 // and may enable from cli option or when using control socket
3193 if (options_->do_progress_updates) {
3194 // clang-format off
3195 std::vector<std::string> am_args = {
3196 "--receiver-permission", "android.permission.DUMP",
3197 };
3198 // clang-format on
3199 // Send STARTED broadcast for apps that listen to bugreport generation events
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003200 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED",
3201 am_args, multiuser_get_user_id(calling_uid));
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003202 if (options_->progress_updates_to_socket) {
3203 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08003204 }
3205 }
3206
Nick Kralevichf3599b32016-01-25 15:05:16 -08003207 /* read /proc/cmdline before dropping root */
3208 FILE *cmdline = fopen("/proc/cmdline", "re");
3209 if (cmdline) {
3210 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
3211 fclose(cmdline);
3212 }
3213
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003214 if (options_->do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08003215 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05003216 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003217
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003218 if (zip_file != nullptr) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003219 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
3220 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003221 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08003222 }
3223 }
3224
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003225 int dup_stdout_fd;
3226 int dup_stderr_fd;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003227 // Redirect stderr to log_path_ for debugging.
3228 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
3229 if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
3230 return ERROR;
3231 }
3232 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
3233 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
3234 strerror(errno));
3235 }
Nandana Dutt979388e2018-11-30 16:48:55 +00003236
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003237 // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
3238 // moved into zip file later, if zipping.
3239 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
3240 // TODO: why not write to a file instead of stdout to overcome this problem?
3241 /* TODO: rather than generating a text file now and zipping it later,
3242 it would be more efficient to redirect stdout to the zip entry
3243 directly, but the libziparchive doesn't support that option yet. */
3244 if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
3245 return ERROR;
3246 }
3247 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
3248 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
3249 tmp_path_.c_str(), strerror(errno));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003250 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08003251
3252 // Don't buffer stdout
3253 setvbuf(stdout, nullptr, _IONBF, 0);
3254
Rhed Jao5377d792020-07-16 17:37:39 +08003255 // Enable the parallel run if the client requests to output to a file.
3256 EnableParallelRunIfNeeded();
3257 // Using scope guard to make sure the dump pool can be shut down correctly.
3258 auto scope_guard_to_shutdown_pool = android::base::make_scope_guard([=]() {
3259 ShutdownDumpPool();
3260 });
3261
Felipe Leme608385d2016-02-01 10:35:38 -08003262 // NOTE: there should be no stdout output until now, otherwise it would break the header.
3263 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08003264 // duration is logged into MYLOG instead.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003265 PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003266
Kean Mariotti853b73a2023-07-27 12:40:30 +00003267 bool is_dumpstate_restricted =
3268 options_->telephony_only || options_->wifi_only || options_->limited_only;
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003269 if (!is_dumpstate_restricted) {
3270 // Snapshot the system trace now (if running) to avoid that dumpstate's
3271 // own activity pushes out interesting data from the trace ring buffer.
3272 // The trace file is added to the zip by MaybeAddSystemTraceToZip().
3273 MaybeSnapshotSystemTrace();
Yohei Yukawa95305b32021-03-09 07:54:27 -08003274
Kean Mariotti853b73a2023-07-27 12:40:30 +00003275 // Invoke critical dumpsys to preserve system state, before doing anything else.
3276 RunDumpsysCritical();
3277
Kean Mariotti306633e2022-09-05 16:30:47 +00003278 // Snapshot the UI traces now (if running).
3279 // The trace files will be added to bugreport later.
3280 MaybeSnapshotUiTraces();
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003281 }
Kean Mariotti853b73a2023-07-27 12:40:30 +00003282
3283 MaybeTakeEarlyScreenshot();
Gavin Corkery6968f552020-11-22 18:09:05 +00003284 onUiIntensiveBugreportDumpsFinished(calling_uid);
3285 MaybeCheckUserConsent(calling_uid, calling_package);
3286 if (options_->telephony_only) {
3287 DumpstateTelephonyOnly(calling_package);
3288 } else if (options_->wifi_only) {
3289 DumpstateWifiOnly();
3290 } else if (options_->limited_only) {
3291 DumpstateLimitedOnly();
Elis Elliott8e401ad2023-08-08 11:18:59 +00003292 } else if (options_->onboarding_only) {
3293 DumpstateOnboardingOnly();
Gavin Corkery6968f552020-11-22 18:09:05 +00003294 } else {
Nandana Dutt4be45d12018-09-26 15:04:23 +01003295 // Dump state for the default case. This also drops root.
Jichao Lie89d9c12019-11-21 19:02:51 -08003296 RunStatus s = DumpstateDefaultAfterCritical();
Nandana Dutt5c390032019-03-12 10:52:56 +00003297 if (s != RunStatus::OK) {
Nandana Duttaac6f582019-07-26 14:32:47 +01003298 if (s == RunStatus::USER_CONSENT_DENIED) {
Nandana Dutt5c390032019-03-12 10:52:56 +00003299 HandleUserConsentDenied();
3300 }
3301 return s;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08003302 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07003303 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07003304
Felipe Leme55b42a62015-11-10 17:39:08 -08003305 /* close output if needed */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003306 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003307
Abhijeet Kaure370d682019-10-01 16:49:30 +01003308 // Zip the (now complete) .tmp file within the internal directory.
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003309 ATRACE_BEGIN("FinalizeFile");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003310 FinalizeFile();
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003311 ATRACE_END();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003312
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003313 // Share the final file with the caller if the user has consented or Shell is the caller.
Nandana Duttd2f5f082019-01-18 17:13:52 +00003314 Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
Gavin Corkerya44686c2022-11-23 18:16:51 +00003315 if (CalledByApi() && !options_->is_consent_deferred) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003316 status = CopyBugreportIfUserConsented(calling_uid);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003317 if (status != Dumpstate::RunStatus::OK &&
3318 status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3319 // Do an early return if there were errors. We make an exception for consent
3320 // timing out because it's possible the user got distracted. In this case the
3321 // bugreport is not shared but made available for manual retrieval.
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003322 MYLOGI("User denied consent. Returning\n");
Nandana Duttd2f5f082019-01-18 17:13:52 +00003323 return status;
3324 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003325 if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3326 MYLOGI(
3327 "Did not receive user consent yet."
3328 " Will not copy the bugreport artifacts to caller.\n");
Abhijeet Kaur57627412019-04-17 16:00:09 +01003329 const String16 incidentcompanion("incidentcompanion");
3330 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
3331 if (ics != nullptr) {
3332 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3333 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3334 consent_callback_.get());
3335 } else {
3336 MYLOGD("Unable to cancel user consent; incidentcompanion service unavailable\n");
3337 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003338 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003339 }
3340
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003341 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003342 if (options_->do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09003343 for (int i = 0; i < 3; i++) {
3344 Vibrate(75);
3345 usleep((75 + 50) * 1000);
3346 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003347 }
3348
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003349 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
3350 progress_->GetInitialMax());
3351 progress_->Save();
3352 MYLOGI("done (id %d)\n", id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003353
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003354 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08003355
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003356 if (control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07003357 MYLOGD("Closing control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003358 close(control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07003359 }
3360
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003361 tombstone_data_.clear();
3362 anr_data_.clear();
Woody Lin20767a92022-11-29 15:50:24 +08003363 shutdown_checkpoints_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01003364
Nandana Duttd2f5f082019-01-18 17:13:52 +00003365 return (consent_callback_ != nullptr &&
3366 consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
3367 ? USER_CONSENT_TIMED_OUT
3368 : RunStatus::OK;
3369}
3370
Paul Chang0d2aad72020-02-13 20:04:03 +08003371void Dumpstate::MaybeTakeEarlyScreenshot() {
3372 if (!options_->do_screenshot || !do_early_screenshot_) {
3373 return;
3374 }
3375
3376 TakeScreenshot();
3377}
3378
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003379void Dumpstate::MaybeSnapshotSystemTrace() {
Kean Mariotti853b73a2023-07-27 12:40:30 +00003380 // When capturing traces via bugreport handler (BH), this function will be invoked twice:
3381 // 1) When BH invokes IDumpstate::PreDumpUiData()
3382 // 2) When BH invokes IDumpstate::startBugreport(flags = BUGREPORT_USE_PREDUMPED_UI_DATA)
3383 // In this case we don't want to re-invoke perfetto in step 2.
3384 // In all other standard invocation states, this function is invoked once
3385 // without the flag BUGREPORT_USE_PREDUMPED_UI_DATA.
3386 if (options_->use_predumped_ui_data) {
3387 return;
3388 }
3389
3390 // If a stale file exists already, remove it.
3391 unlink(SYSTEM_TRACE_SNAPSHOT);
3392
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003393 // If a background system trace is happening and is marked as "suitable for
3394 // bugreport" (i.e. bugreport_score > 0 in the trace config), this command
3395 // will stop it and serialize into SYSTEM_TRACE_SNAPSHOT. In the (likely)
3396 // case that no trace is ongoing, this command is a no-op.
3397 // Note: this should not be enqueued as we need to freeze the trace before
3398 // dumpstate starts. Otherwise the trace ring buffers will contain mostly
3399 // the dumpstate's own activity which is irrelevant.
Kean Mariotti853b73a2023-07-27 12:40:30 +00003400 RunCommand("SERIALIZE PERFETTO TRACE", {"perfetto", "--save-for-bugreport"},
3401 CommandOptions::WithTimeout(10).DropRoot().CloseAllFileDescriptorsOnExec().Build());
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003402 // MaybeAddSystemTraceToZip() will take care of copying the trace in the zip
3403 // file in the later stages.
3404}
3405
Kean Mariotti306633e2022-09-05 16:30:47 +00003406void Dumpstate::MaybeSnapshotUiTraces() {
3407 if (PropertiesHelper::IsUserBuild() || options_->use_predumped_ui_data) {
3408 return;
3409 }
3410
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003411 const std::vector<std::vector<std::string>> dumpTracesForBugReportCommands = {
3412 {"dumpsys", "activity", "service", "SystemUIService", "WMShell", "protolog",
3413 "save-for-bugreport"},
3414 {"dumpsys", "activity", "service", "SystemUIService", "WMShell", "transitions", "tracing",
3415 "save-for-bugreport"},
3416 {"cmd", "input_method", "tracing", "save-for-bugreport"},
3417 {"cmd", "window", "tracing", "save-for-bugreport"},
3418 {"cmd", "window", "shell", "tracing", "save-for-bugreport"},
3419 };
Hongwei Wang39229132023-01-24 15:09:59 -08003420
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003421 for (const auto& command : dumpTracesForBugReportCommands) {
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003422 RunCommand(
3423 // Empty name because it's not intended to be classified as a bugreport section.
3424 // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003425 "", command,
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003426 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
3427 }
Kean Mariotti306633e2022-09-05 16:30:47 +00003428}
3429
3430void Dumpstate::MaybeAddUiTracesToZip() {
3431 if (PropertiesHelper::IsUserBuild()) {
3432 return;
3433 }
3434
3435 ds.AddDir(WMTRACE_DATA_DIR, false);
Yohei Yukawa95305b32021-03-09 07:54:27 -08003436}
3437
Paul Changeb4b4642020-05-28 22:05:47 +08003438void Dumpstate::onUiIntensiveBugreportDumpsFinished(int32_t calling_uid) {
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003439 if (multiuser_get_app_id(calling_uid) == AID_SHELL || !CalledByApi()) {
Paul Changc490e662020-04-11 18:14:09 +08003440 return;
3441 }
3442 if (listener_ != nullptr) {
3443 // Let listener know ui intensive bugreport dumps are finished, then it can do event
3444 // handling if required.
Paul Changeb4b4642020-05-28 22:05:47 +08003445 listener_->onUiIntensiveBugreportDumpsFinished();
Paul Changc490e662020-04-11 18:14:09 +08003446 }
3447}
3448
Jichao Lie89d9c12019-11-21 19:02:51 -08003449void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) {
Gavin Corkerya44686c2022-11-23 18:16:51 +00003450 if (multiuser_get_app_id(calling_uid) == AID_SHELL ||
3451 !CalledByApi() || options_->is_consent_deferred) {
3452 // No need to get consent for shell triggered dumpstates, or not
3453 // through bugreporting API (i.e. no fd to copy back), or when consent
3454 // is deferred.
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003455 return;
3456 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003457 consent_callback_ = new ConsentCallback();
3458 const String16 incidentcompanion("incidentcompanion");
3459 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
Jichao Lie89d9c12019-11-21 19:02:51 -08003460 android::String16 package(calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003461 if (ics != nullptr) {
3462 MYLOGD("Checking user consent via incidentcompanion service\n");
Steven Leeb573eb82022-11-29 22:31:35 +08003463 int flags = 0x1; // IncidentManager.FLAG_CONFIRMATION_DIALOG
3464 if (IsConsentlessBugreportAllowed(*options_)) {
3465 flags |= 0x2; // IncidentManager.FLAG_ALLOW_CONSENTLESS_BUGREPORT
3466 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003467 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
Steven Leeb573eb82022-11-29 22:31:35 +08003468 calling_uid, package, String16(), String16(), flags, consent_callback_.get());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003469 } else {
3470 MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
3471 }
3472}
3473
Nandana Dutt5c390032019-03-12 10:52:56 +00003474bool Dumpstate::IsUserConsentDenied() const {
3475 return ds.consent_callback_ != nullptr &&
3476 ds.consent_callback_->getResult() == UserConsentResult::DENIED;
3477}
3478
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01003479bool Dumpstate::CalledByApi() const {
3480 return ds.options_->bugreport_fd.get() != -1 ? true : false;
3481}
3482
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003483void Dumpstate::CleanupTmpFiles() {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003484 android::os::UnlinkAndLogOnError(tmp_path_);
3485 android::os::UnlinkAndLogOnError(screenshot_path_);
3486 android::os::UnlinkAndLogOnError(path_);
Gavin Corkery789d7a52021-02-24 23:52:35 +00003487 if (dump_traces_path != nullptr) {
3488 android::os::UnlinkAndLogOnError(dump_traces_path);
3489 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003490}
3491
Rhed Jao5377d792020-07-16 17:37:39 +08003492void Dumpstate::EnableParallelRunIfNeeded() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003493 if (!PropertiesHelper::IsParallelRun()) {
Rhed Jao5377d792020-07-16 17:37:39 +08003494 return;
3495 }
3496 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003497 zip_entry_tasks_ = std::make_unique<TaskQueue>();
Rhed Jao5377d792020-07-16 17:37:39 +08003498}
3499
3500void Dumpstate::ShutdownDumpPool() {
3501 if (dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08003502 dump_pool_.reset();
Rhed Jao5377d792020-07-16 17:37:39 +08003503 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003504 if (zip_entry_tasks_) {
3505 zip_entry_tasks_->run(/* do_cancel = */true);
3506 zip_entry_tasks_ = nullptr;
3507 }
3508}
3509
3510void Dumpstate::EnqueueAddZipEntryAndCleanupIfNeeded(const std::string& entry_name,
3511 const std::string& entry_path) {
3512 auto func_add_zip_entry_and_cleanup = [=](bool task_cancelled) {
3513 if (!task_cancelled) {
3514 AddZipEntry(entry_name, entry_path);
3515 }
3516 android::os::UnlinkAndLogOnError(entry_path);
3517 };
3518 if (zip_entry_tasks_) {
3519 // Enqueues AddZipEntryAndCleanup function if the parallel run is enabled.
3520 zip_entry_tasks_->add(func_add_zip_entry_and_cleanup, _1);
3521 } else {
3522 // Invokes AddZipEntryAndCleanup immediately
3523 std::invoke(func_add_zip_entry_and_cleanup, /* task_cancelled = */false);
3524 }
Rhed Jao5377d792020-07-16 17:37:39 +08003525}
3526
Nandana Duttd2f5f082019-01-18 17:13:52 +00003527Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
3528 MYLOGD("User denied consent; deleting files and returning\n");
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003529 CleanupTmpFiles();
Nandana Duttd2f5f082019-01-18 17:13:52 +00003530 return USER_CONSENT_DENIED;
3531}
3532
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003533Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented(int32_t calling_uid) {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003534 // If the caller has asked to copy the bugreport over to their directory, we need explicit
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003535 // user consent (unless the caller is Shell).
3536 UserConsentResult consent_result;
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003537 if (multiuser_get_app_id(calling_uid) == AID_SHELL) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003538 consent_result = UserConsentResult::APPROVED;
3539 } else {
3540 consent_result = consent_callback_->getResult();
3541 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003542 if (consent_result == UserConsentResult::UNAVAILABLE) {
3543 // User has not responded yet.
3544 uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
Hunter Knepshield70610fa2020-01-03 15:27:33 -08003545 // Telephony is a fast report type, particularly on user builds where information may be
3546 // more aggressively limited. To give the user time to read the consent dialog, increase the
3547 // timeout.
3548 uint64_t timeout_ms = options_->telephony_only ? TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS
3549 : USER_CONSENT_TIMEOUT_MS;
3550 if (elapsed_ms < timeout_ms) {
3551 uint delay_seconds = (timeout_ms - elapsed_ms) / 1000;
Nandana Duttd2f5f082019-01-18 17:13:52 +00003552 MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
3553 sleep(delay_seconds);
3554 }
3555 consent_result = consent_callback_->getResult();
3556 }
3557 if (consent_result == UserConsentResult::DENIED) {
3558 // User has explicitly denied sharing with the app. To be safe delete the
3559 // internal bugreport & tmp files.
3560 return HandleUserConsentDenied();
3561 }
3562 if (consent_result == UserConsentResult::APPROVED) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00003563 bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
3564 if (copy_succeeded) {
3565 android::os::UnlinkAndLogOnError(path_);
Abhijeet Kaur9ce94672020-04-01 17:22:36 +01003566 if (options_->do_screenshot &&
3567 options_->screenshot_fd.get() != -1 &&
3568 !options_->is_screenshot_copied) {
3569 copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
3570 options_->screenshot_fd.get());
3571 options_->is_screenshot_copied = copy_succeeded;
3572 if (copy_succeeded) {
3573 android::os::UnlinkAndLogOnError(screenshot_path_);
3574 }
3575 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003576 }
3577 return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
3578 } else if (consent_result == UserConsentResult::UNAVAILABLE) {
3579 // consent_result is still UNAVAILABLE. The user has likely not responded yet.
3580 // Since we do not have user consent to share the bugreport it does not get
3581 // copied over to the calling app but remains in the internal directory from
3582 // where the user can manually pull it.
Paul Changce644212021-05-11 16:06:45 +08003583 std::string final_path = GetPath(".zip");
3584 bool copy_succeeded = android::os::CopyFileToFile(path_, final_path);
3585 if (copy_succeeded) {
3586 android::os::UnlinkAndLogOnError(path_);
3587 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003588 return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
3589 }
3590 // Unknown result; must be a programming error.
3591 MYLOGE("Unknown user consent result:%d\n", consent_result);
3592 return Dumpstate::RunStatus::ERROR;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003593}
3594
Nandana Duttf02564e2019-02-15 15:24:24 +00003595Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003596 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
3597 Dumpstate::RunStatus status = options->Initialize(argc, argv);
3598 if (status == Dumpstate::RunStatus::OK) {
Nandana Duttf02564e2019-02-15 15:24:24 +00003599 SetOptions(std::move(options));
Nandana Duttd2f5f082019-01-18 17:13:52 +00003600 // When directly running dumpstate binary, the output is not expected to be written
3601 // to any external file descriptor.
Nandana Duttf02564e2019-02-15 15:24:24 +00003602 assert(options_->bugreport_fd.get() == -1);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003603
3604 // calling_uid and calling_package are for user consent to share the bugreport with
Abhijeet Kaura407fb82020-03-27 12:51:12 +00003605 // an app; they are irrelevant here because bugreport is triggered via command line.
3606 // Update Last ID before calling Run().
3607 Initialize();
Nikhil Kumarb70622a2023-06-15 15:37:19 +01003608 status = Run(0 /* calling_uid */, "" /* calling_package */);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003609 }
Nandana Duttf02564e2019-02-15 15:24:24 +00003610 return status;
3611}
3612
3613/* Main entry point for dumpstate binary. */
3614int run_main(int argc, char* argv[]) {
3615 Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003616
3617 switch (status) {
3618 case Dumpstate::RunStatus::OK:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003619 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003620 case Dumpstate::RunStatus::HELP:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003621 ShowUsage();
3622 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003623 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003624 fprintf(stderr, "Invalid combination of args\n");
3625 ShowUsage();
3626 exit(1);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003627 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003628 FALLTHROUGH_INTENDED;
3629 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3630 FALLTHROUGH_INTENDED;
3631 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003632 exit(2);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003633 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003634}
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003635
3636// TODO(111441001): Default DumpOptions to sensible values.
3637Dumpstate::Dumpstate(const std::string& version)
3638 : pid_(getpid()),
3639 options_(new Dumpstate::DumpOptions()),
Nandana Dutt402a8392019-06-14 14:25:13 +01003640 last_reported_percent_progress_(0),
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003641 version_(version),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003642 now_(time(nullptr)),
3643 open_socket_fn_(open_socket) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003644}
3645
3646Dumpstate& Dumpstate::GetInstance() {
3647 static Dumpstate singleton_(android::base::GetProperty("dumpstate.version", VERSION_CURRENT));
3648 return singleton_;
3649}
3650
Rhed Jao5377d792020-07-16 17:37:39 +08003651DurationReporter::DurationReporter(const std::string& title, bool logcat_only, bool verbose,
3652 int duration_fd) : title_(title), logcat_only_(logcat_only), verbose_(verbose),
3653 duration_fd_(duration_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003654 if (!title_.empty()) {
3655 started_ = Nanotime();
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003656 if (title_.find("SHOW MAP") == std::string::npos) {
3657 ATRACE_ASYNC_BEGIN(title_.c_str(), 0);
3658 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003659 }
3660}
3661
3662DurationReporter::~DurationReporter() {
3663 if (!title_.empty()) {
3664 float elapsed = (float)(Nanotime() - started_) / NANOS_PER_SEC;
chenqiwuaf8b2d92019-12-12 18:53:51 +08003665 if (elapsed >= .5f || verbose_) {
3666 MYLOGD("Duration of '%s': %.2fs\n", title_.c_str(), elapsed);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003667 }
chenqiwuaf8b2d92019-12-12 18:53:51 +08003668 if (!logcat_only_) {
3669 // Use "Yoda grammar" to make it easier to grep|sort sections.
Rhed Jao5377d792020-07-16 17:37:39 +08003670 dprintf(duration_fd_, "------ %.3fs was the duration of '%s' ------\n",
3671 elapsed, title_.c_str());
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003672 }
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003673 if (title_.find("SHOW MAP") == std::string::npos) {
3674 ATRACE_ASYNC_END(title_.c_str(), 0);
3675 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003676 }
3677}
3678
3679const int32_t Progress::kDefaultMax = 5000;
3680
3681Progress::Progress(const std::string& path) : Progress(Progress::kDefaultMax, 1.1, path) {
3682}
3683
3684Progress::Progress(int32_t initial_max, int32_t progress, float growth_factor)
3685 : Progress(initial_max, growth_factor, "") {
3686 progress_ = progress;
3687}
3688
3689Progress::Progress(int32_t initial_max, float growth_factor, const std::string& path)
3690 : initial_max_(initial_max),
3691 progress_(0),
3692 max_(initial_max),
3693 growth_factor_(growth_factor),
3694 n_runs_(0),
3695 average_max_(0),
3696 path_(path) {
3697 if (!path_.empty()) {
3698 Load();
3699 }
3700}
3701
3702void Progress::Load() {
3703 MYLOGD("Loading stats from %s\n", path_.c_str());
3704 std::string content;
3705 if (!android::base::ReadFileToString(path_, &content)) {
3706 MYLOGI("Could not read stats from %s; using max of %d\n", path_.c_str(), max_);
3707 return;
3708 }
3709 if (content.empty()) {
3710 MYLOGE("No stats (empty file) on %s; using max of %d\n", path_.c_str(), max_);
3711 return;
3712 }
3713 std::vector<std::string> lines = android::base::Split(content, "\n");
3714
3715 if (lines.size() < 1) {
3716 MYLOGE("Invalid stats on file %s: not enough lines (%d). Using max of %d\n", path_.c_str(),
3717 (int)lines.size(), max_);
3718 return;
3719 }
3720 char* ptr;
3721 n_runs_ = strtol(lines[0].c_str(), &ptr, 10);
3722 average_max_ = strtol(ptr, nullptr, 10);
3723 if (n_runs_ <= 0 || average_max_ <= 0 || n_runs_ > STATS_MAX_N_RUNS ||
3724 average_max_ > STATS_MAX_AVERAGE) {
3725 MYLOGE("Invalid stats line on file %s: %s\n", path_.c_str(), lines[0].c_str());
3726 initial_max_ = Progress::kDefaultMax;
3727 } else {
3728 initial_max_ = average_max_;
3729 }
3730 max_ = initial_max_;
3731
3732 MYLOGI("Average max progress: %d in %d runs; estimated max: %d\n", average_max_, n_runs_, max_);
3733}
3734
3735void Progress::Save() {
3736 int32_t total = n_runs_ * average_max_ + progress_;
3737 int32_t runs = n_runs_ + 1;
3738 int32_t average = floor(((float)total) / runs);
3739 MYLOGI("Saving stats (total=%d, runs=%d, average=%d) on %s\n", total, runs, average,
3740 path_.c_str());
3741 if (path_.empty()) {
3742 return;
3743 }
3744
3745 std::string content = android::base::StringPrintf("%d %d\n", runs, average);
3746 if (!android::base::WriteStringToFile(content, path_)) {
3747 MYLOGE("Could not save stats on %s\n", path_.c_str());
3748 }
3749}
3750
3751int32_t Progress::Get() const {
3752 return progress_;
3753}
3754
3755bool Progress::Inc(int32_t delta_sec) {
3756 bool changed = false;
3757 if (delta_sec >= 0) {
3758 progress_ += delta_sec;
3759 if (progress_ > max_) {
3760 int32_t old_max = max_;
3761 max_ = floor((float)progress_ * growth_factor_);
3762 MYLOGD("Adjusting max progress from %d to %d\n", old_max, max_);
3763 changed = true;
3764 }
3765 }
3766 return changed;
3767}
3768
3769int32_t Progress::GetMax() const {
3770 return max_;
3771}
3772
3773int32_t Progress::GetInitialMax() const {
3774 return initial_max_;
3775}
3776
3777void Progress::Dump(int fd, const std::string& prefix) const {
3778 const char* pr = prefix.c_str();
3779 dprintf(fd, "%sprogress: %d\n", pr, progress_);
3780 dprintf(fd, "%smax: %d\n", pr, max_);
3781 dprintf(fd, "%sinitial_max: %d\n", pr, initial_max_);
3782 dprintf(fd, "%sgrowth_factor: %0.2f\n", pr, growth_factor_);
3783 dprintf(fd, "%spath: %s\n", pr, path_.c_str());
3784 dprintf(fd, "%sn_runs: %d\n", pr, n_runs_);
3785 dprintf(fd, "%saverage_max: %d\n", pr, average_max_);
3786}
3787
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003788std::string Dumpstate::GetPath(const std::string& suffix) const {
3789 return GetPath(bugreport_internal_dir_, suffix);
3790}
3791
3792std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
3793 return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
3794 name_.c_str(), suffix.c_str());
3795}
3796
3797void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
3798 progress_ = std::move(progress);
3799}
3800
3801void for_each_userid(void (*func)(int), const char *header) {
3802 std::string title = header == nullptr ? "for_each_userid" : android::base::StringPrintf(
3803 "for_each_userid(%s)", header);
3804 DurationReporter duration_reporter(title);
3805 if (PropertiesHelper::IsDryRun()) return;
3806
3807 DIR *d;
3808 struct dirent *de;
3809
3810 if (header) printf("\n------ %s ------\n", header);
3811 func(0);
3812
3813 if (!(d = opendir("/data/system/users"))) {
3814 printf("Failed to open /data/system/users (%s)\n", strerror(errno));
3815 return;
3816 }
3817
3818 while ((de = readdir(d))) {
3819 int userid;
3820 if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
3821 continue;
3822 }
3823 func(userid);
3824 }
3825
3826 closedir(d);
3827}
3828
3829static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
3830 DIR *d;
3831 struct dirent *de;
3832
3833 if (!(d = opendir("/proc"))) {
3834 printf("Failed to open /proc (%s)\n", strerror(errno));
3835 return;
3836 }
3837
3838 if (header) printf("\n------ %s ------\n", header);
3839 while ((de = readdir(d))) {
3840 if (ds.IsUserConsentDenied()) {
3841 MYLOGE(
3842 "Returning early because user denied consent to share bugreport with calling app.");
3843 closedir(d);
3844 return;
3845 }
3846 int pid;
3847 int fd;
3848 char cmdpath[255];
3849 char cmdline[255];
3850
3851 if (!(pid = atoi(de->d_name))) {
3852 continue;
3853 }
3854
3855 memset(cmdline, 0, sizeof(cmdline));
3856
3857 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
3858 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3859 TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
3860 close(fd);
3861 if (cmdline[0]) {
3862 helper(pid, cmdline, arg);
3863 continue;
3864 }
3865 }
3866
3867 // if no cmdline, a kernel thread has comm
3868 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
3869 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3870 TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
3871 close(fd);
3872 if (cmdline[1]) {
3873 cmdline[0] = '[';
3874 size_t len = strcspn(cmdline, "\f\b\r\n");
3875 cmdline[len] = ']';
3876 cmdline[len+1] = '\0';
3877 }
3878 }
3879 if (!cmdline[0]) {
3880 strcpy(cmdline, "N/A");
3881 }
3882 helper(pid, cmdline, arg);
3883 }
3884
3885 closedir(d);
3886}
3887
3888static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
3889 for_each_pid_func *func = (for_each_pid_func*) arg;
3890 func(pid, cmdline);
3891}
3892
3893void for_each_pid(for_each_pid_func func, const char *header) {
3894 std::string title = header == nullptr ? "for_each_pid"
3895 : android::base::StringPrintf("for_each_pid(%s)", header);
3896 DurationReporter duration_reporter(title);
3897 if (PropertiesHelper::IsDryRun()) return;
3898
3899 __for_each_pid(for_each_pid_helper, header, (void *) func);
3900}
3901
3902static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
3903 DIR *d;
3904 struct dirent *de;
3905 char taskpath[255];
3906 for_each_tid_func *func = (for_each_tid_func *) arg;
3907
3908 snprintf(taskpath, sizeof(taskpath), "/proc/%d/task", pid);
3909
3910 if (!(d = opendir(taskpath))) {
3911 printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
3912 return;
3913 }
3914
3915 func(pid, pid, cmdline);
3916
3917 while ((de = readdir(d))) {
3918 if (ds.IsUserConsentDenied()) {
3919 MYLOGE(
3920 "Returning early because user denied consent to share bugreport with calling app.");
3921 closedir(d);
3922 return;
3923 }
3924 int tid;
3925 int fd;
3926 char commpath[255];
3927 char comm[255];
3928
3929 if (!(tid = atoi(de->d_name))) {
3930 continue;
3931 }
3932
3933 if (tid == pid)
3934 continue;
3935
3936 snprintf(commpath, sizeof(commpath), "/proc/%d/comm", tid);
3937 memset(comm, 0, sizeof(comm));
3938 if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
3939 strcpy(comm, "N/A");
3940 } else {
3941 char *c;
3942 TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
3943 close(fd);
3944
3945 c = strrchr(comm, '\n');
3946 if (c) {
3947 *c = '\0';
3948 }
3949 }
3950 func(pid, tid, comm);
3951 }
3952
3953 closedir(d);
3954}
3955
3956void for_each_tid(for_each_tid_func func, const char *header) {
3957 std::string title = header == nullptr ? "for_each_tid"
3958 : android::base::StringPrintf("for_each_tid(%s)", header);
3959 DurationReporter duration_reporter(title);
3960
3961 if (PropertiesHelper::IsDryRun()) return;
3962
3963 __for_each_pid(for_each_tid_helper, header, (void *) func);
3964}
3965
3966void show_wchan(int pid, int tid, const char *name) {
3967 if (PropertiesHelper::IsDryRun()) return;
3968
3969 char path[255];
3970 char buffer[255];
3971 int fd, ret, save_errno;
3972 char name_buffer[255];
3973
3974 memset(buffer, 0, sizeof(buffer));
3975
3976 snprintf(path, sizeof(path), "/proc/%d/wchan", tid);
3977 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
3978 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
3979 return;
3980 }
3981
3982 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3983 save_errno = errno;
3984 close(fd);
3985
3986 if (ret < 0) {
3987 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
3988 return;
3989 }
3990
3991 snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
3992 pid == tid ? 0 : 3, "", name);
3993
3994 printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
3995
3996 return;
3997}
3998
3999// print time in centiseconds
4000static void snprcent(char *buffer, size_t len, size_t spc,
4001 unsigned long long time) {
4002 static long hz; // cache discovered hz
4003
4004 if (hz <= 0) {
4005 hz = sysconf(_SC_CLK_TCK);
4006 if (hz <= 0) {
4007 hz = 1000;
4008 }
4009 }
4010
4011 // convert to centiseconds
4012 time = (time * 100 + (hz / 2)) / hz;
4013
4014 char str[16];
4015
4016 snprintf(str, sizeof(str), " %llu.%02u",
4017 time / 100, (unsigned)(time % 100));
4018 size_t offset = strlen(buffer);
4019 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
4020 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
4021}
4022
4023// print permille as a percent
4024static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
4025 char str[16];
4026
4027 snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
4028 size_t offset = strlen(buffer);
4029 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
4030 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
4031}
4032
4033void show_showtime(int pid, const char *name) {
4034 if (PropertiesHelper::IsDryRun()) return;
4035
4036 char path[255];
4037 char buffer[1023];
4038 int fd, ret, save_errno;
4039
4040 memset(buffer, 0, sizeof(buffer));
4041
4042 snprintf(path, sizeof(path), "/proc/%d/stat", pid);
4043 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
4044 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
4045 return;
4046 }
4047
4048 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
4049 save_errno = errno;
4050 close(fd);
4051
4052 if (ret < 0) {
4053 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
4054 return;
4055 }
4056
4057 // field 14 is utime
4058 // field 15 is stime
4059 // field 42 is iotime
4060 unsigned long long utime = 0, stime = 0, iotime = 0;
4061 if (sscanf(buffer,
4062 "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
4063 "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
4064 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
4065 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
4066 &utime, &stime, &iotime) != 3) {
4067 return;
4068 }
4069
4070 unsigned long long total = utime + stime;
4071 if (!total) {
4072 return;
4073 }
4074
4075 unsigned permille = (iotime * 1000 + (total / 2)) / total;
4076 if (permille > 1000) {
4077 permille = 1000;
4078 }
4079
4080 // try to beautify and stabilize columns at <80 characters
4081 snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
4082 if ((name[0] != '[') || utime) {
4083 snprcent(buffer, sizeof(buffer), 57, utime);
4084 }
4085 snprcent(buffer, sizeof(buffer), 65, stime);
4086 if ((name[0] != '[') || iotime) {
4087 snprcent(buffer, sizeof(buffer), 73, iotime);
4088 }
4089 if (iotime) {
4090 snprdec(buffer, sizeof(buffer), 79, permille);
4091 }
4092 puts(buffer); // adds a trailing newline
4093
4094 return;
4095}
4096
4097void do_dmesg() {
4098 const char *title = "KERNEL LOG (dmesg)";
4099 DurationReporter duration_reporter(title);
4100 printf("------ %s ------\n", title);
4101
4102 if (PropertiesHelper::IsDryRun()) return;
4103
4104 /* Get size of kernel buffer */
4105 int size = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
4106 if (size <= 0) {
4107 printf("Unexpected klogctl return value: %d\n\n", size);
4108 return;
4109 }
4110 char *buf = (char *) malloc(size + 1);
4111 if (buf == nullptr) {
4112 printf("memory allocation failed\n\n");
4113 return;
4114 }
4115 int retval = klogctl(KLOG_READ_ALL, buf, size);
4116 if (retval < 0) {
4117 printf("klogctl failure\n\n");
4118 free(buf);
4119 return;
4120 }
4121 buf[retval] = '\0';
4122 printf("%s\n\n", buf);
4123 free(buf);
4124 return;
4125}
4126
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004127int Dumpstate::DumpFile(const std::string& title, const std::string& path) {
4128 DurationReporter duration_reporter(title);
4129
4130 int status = DumpFileToFd(STDOUT_FILENO, title, path);
4131
4132 UpdateProgress(WEIGHT_FILE);
4133
4134 return status;
4135}
4136
4137int read_file_as_long(const char *path, long int *output) {
4138 int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
4139 if (fd < 0) {
4140 int err = errno;
4141 MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
4142 return -1;
4143 }
4144 char buffer[50];
4145 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
4146 if (bytes_read == -1) {
4147 MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
4148 return -2;
4149 }
4150 if (bytes_read == 0) {
4151 MYLOGE("File %s is empty\n", path);
4152 return -3;
4153 }
4154 *output = atoi(buffer);
4155 return 0;
4156}
4157
4158/* calls skip to gate calling dump_from_fd recursively
4159 * in the specified directory. dump_from_fd defaults to
4160 * dump_file_from_fd above when set to NULL. skip defaults
4161 * to false when set to NULL. dump_from_fd will always be
4162 * called with title NULL.
4163 */
4164int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
4165 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4166 DurationReporter duration_reporter(title);
4167 DIR *dirp;
4168 struct dirent *d;
4169 char *newpath = nullptr;
4170 const char *slash = "/";
4171 int retval = 0;
4172
4173 if (!title.empty()) {
4174 printf("------ %s (%s) ------\n", title.c_str(), dir);
4175 }
4176 if (PropertiesHelper::IsDryRun()) return 0;
4177
4178 if (dir[strlen(dir) - 1] == '/') {
4179 ++slash;
4180 }
4181 dirp = opendir(dir);
4182 if (dirp == nullptr) {
4183 retval = -errno;
4184 MYLOGE("%s: %s\n", dir, strerror(errno));
4185 return retval;
4186 }
4187
4188 if (!dump_from_fd) {
4189 dump_from_fd = dump_file_from_fd;
4190 }
4191 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4192 if ((d->d_name[0] == '.')
4193 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4194 || (d->d_name[1] == '\0'))) {
4195 continue;
4196 }
4197 asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
4198 (d->d_type == DT_DIR) ? "/" : "");
4199 if (!newpath) {
4200 retval = -errno;
4201 continue;
4202 }
4203 if (skip && (*skip)(newpath)) {
4204 continue;
4205 }
4206 if (d->d_type == DT_DIR) {
4207 int ret = dump_files("", newpath, skip, dump_from_fd);
4208 if (ret < 0) {
4209 retval = ret;
4210 }
4211 continue;
4212 }
4213 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
4214 if (fd.get() < 0) {
4215 retval = -1;
4216 printf("*** %s: %s\n", newpath, strerror(errno));
4217 continue;
4218 }
4219 (*dump_from_fd)(nullptr, newpath, fd.get());
4220 }
4221 closedir(dirp);
4222 if (!title.empty()) {
4223 printf("\n");
4224 }
4225 return retval;
4226}
4227
4228/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
4229 * it's possible to avoid issues where opening the file itself can get
4230 * stuck.
4231 */
4232int dump_file_from_fd(const char *title, const char *path, int fd) {
4233 if (PropertiesHelper::IsDryRun()) return 0;
4234
4235 int flags = fcntl(fd, F_GETFL);
4236 if (flags == -1) {
4237 printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
4238 return -1;
4239 } else if (!(flags & O_NONBLOCK)) {
4240 printf("*** %s: fd must have O_NONBLOCK set.\n", path);
4241 return -1;
4242 }
4243 return DumpFileFromFdToFd(title, path, fd, STDOUT_FILENO, PropertiesHelper::IsDryRun());
4244}
4245
4246int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004247 const CommandOptions& options, bool verbose_duration, int out_fd) {
4248 DurationReporter duration_reporter(title, false /* logcat_only */,
4249 verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004250
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004251 int status = RunCommandToFd(out_fd, title, full_command, options);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004252
4253 /* TODO: for now we're simplifying the progress calculation by using the
4254 * timeout as the weight. It's a good approximation for most cases, except when calling dumpsys,
4255 * where its weight should be much higher proportionally to its timeout.
4256 * Ideally, it should use a options.EstimatedDuration() instead...*/
4257 UpdateProgress(options.Timeout());
4258
4259 return status;
4260}
4261
4262void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
Rhed Jaoe017f982020-07-21 17:58:41 +08004263 const CommandOptions& options, long dumpsysTimeoutMs, int out_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004264 long timeout_ms = dumpsysTimeoutMs > 0 ? dumpsysTimeoutMs : options.TimeoutInMs();
4265 std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-T", std::to_string(timeout_ms)};
4266 dumpsys.insert(dumpsys.end(), dumpsys_args.begin(), dumpsys_args.end());
Rhed Jaoe017f982020-07-21 17:58:41 +08004267 RunCommand(title, dumpsys, options, false, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004268}
4269
Dieter Hsu105ad0c2020-09-29 15:23:33 +08004270static int open_socket(const char* service) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004271 int s = android_get_control_socket(service);
4272 if (s < 0) {
4273 MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
4274 return -1;
4275 }
4276 fcntl(s, F_SETFD, FD_CLOEXEC);
4277
4278 // Set backlog to 0 to make sure that queue size will be minimum.
4279 // In Linux, because the minimum queue will be 1, connect() will be blocked
4280 // if the other clients already called connect() and the connection request was not accepted.
4281 if (listen(s, 0) < 0) {
4282 MYLOGE("listen(control socket): %s\n", strerror(errno));
4283 return -1;
4284 }
4285
4286 struct sockaddr addr;
4287 socklen_t alen = sizeof(addr);
Abhijeet Kaur2113cae2019-09-13 09:24:15 +01004288 int fd = accept4(s, &addr, &alen, SOCK_CLOEXEC);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004289
4290 // Close socket just after accept(), to make sure that connect() by client will get error
4291 // when the socket is used by the other services.
4292 // There is still a race condition possibility between accept and close, but there is no way
4293 // to close-on-accept atomically.
4294 // See detail; b/123306389#comment25
4295 close(s);
4296
4297 if (fd < 0) {
4298 MYLOGE("accept(control socket): %s\n", strerror(errno));
4299 return -1;
4300 }
4301
4302 return fd;
4303}
4304
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004305// TODO: should call is_valid_output_file and/or be merged into it.
4306void create_parent_dirs(const char *path) {
4307 char *chp = const_cast<char *> (path);
4308
4309 /* skip initial slash */
4310 if (chp[0] == '/')
4311 chp++;
4312
4313 /* create leading directories, if necessary */
4314 struct stat dir_stat;
4315 while (chp && chp[0]) {
4316 chp = strchr(chp, '/');
4317 if (chp) {
4318 *chp = 0;
4319 if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
4320 MYLOGI("Creating directory %s\n", path);
4321 if (mkdir(path, 0770)) { /* drwxrwx--- */
4322 MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
4323 } else if (chown(path, AID_SHELL, AID_SHELL)) {
4324 MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
4325 }
4326 }
4327 *chp++ = '/';
4328 }
4329 }
4330}
4331
4332bool _redirect_to_file(FILE* redirect, char* path, int truncate_flag) {
4333 create_parent_dirs(path);
4334
4335 int fd = TEMP_FAILURE_RETRY(open(path,
4336 O_WRONLY | O_CREAT | truncate_flag | O_CLOEXEC | O_NOFOLLOW,
4337 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
4338 if (fd < 0) {
4339 MYLOGE("%s: %s\n", path, strerror(errno));
4340 return false;
4341 }
4342
4343 TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
4344 close(fd);
4345 return true;
4346}
4347
4348bool redirect_to_file(FILE* redirect, char* path) {
4349 return _redirect_to_file(redirect, path, O_TRUNC);
4350}
4351
4352bool redirect_to_existing_file(FILE* redirect, char* path) {
4353 return _redirect_to_file(redirect, path, O_APPEND);
4354}
4355
4356void dump_route_tables() {
4357 DurationReporter duration_reporter("DUMP ROUTE TABLES");
4358 if (PropertiesHelper::IsDryRun()) return;
4359 const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
4360 ds.DumpFile("RT_TABLES", RT_TABLES_PATH);
4361 FILE* fp = fopen(RT_TABLES_PATH, "re");
4362 if (!fp) {
4363 printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
4364 return;
4365 }
4366 char table[16];
4367 // Each line has an integer (the table number), a space, and a string (the table name). We only
4368 // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
4369 // Add a fixed max limit so this doesn't go awry.
4370 for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
4371 RunCommand("ROUTE TABLE IPv4", {"ip", "-4", "route", "show", "table", table});
4372 RunCommand("ROUTE TABLE IPv6", {"ip", "-6", "route", "show", "table", table});
4373 }
4374 fclose(fp);
4375}
4376
Li Li830179f2022-01-04 12:53:29 -08004377void dump_frozen_cgroupfs(const char *dir, int level,
4378 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4379 DIR *dirp;
4380 struct dirent *d;
4381 char *newpath = nullptr;
4382
4383 dirp = opendir(dir);
4384 if (dirp == nullptr) {
4385 MYLOGE("%s: %s\n", dir, strerror(errno));
4386 return;
4387 }
4388
4389 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4390 if ((d->d_name[0] == '.')
4391 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4392 || (d->d_name[1] == '\0'))) {
4393 continue;
4394 }
4395 if (d->d_type == DT_DIR) {
4396 asprintf(&newpath, "%s/%s/", dir, d->d_name);
4397 if (!newpath) {
4398 continue;
4399 }
4400 if (level == 0 && !strncmp(d->d_name, "uid_", 4)) {
4401 dump_frozen_cgroupfs(newpath, 1, dump_from_fd);
4402 } else if (level == 1 && !strncmp(d->d_name, "pid_", 4)) {
4403 char *freezer = nullptr;
4404 asprintf(&freezer, "%s/%s", newpath, "cgroup.freeze");
4405 if (freezer) {
4406 FILE* fp = fopen(freezer, "r");
4407 if (fp != NULL) {
4408 int frozen;
4409 fscanf(fp, "%d", &frozen);
4410 if (frozen > 0) {
4411 dump_files("", newpath, skip_none, dump_from_fd);
4412 }
4413 fclose(fp);
4414 }
4415 free(freezer);
4416 }
4417 }
4418 }
4419 }
4420 closedir(dirp);
4421}
4422
4423void dump_frozen_cgroupfs() {
Li Li830179f2022-01-04 12:53:29 -08004424 MYLOGD("Adding frozen processes from %s\n", CGROUPFS_DIR);
4425 DurationReporter duration_reporter("FROZEN CGROUPFS");
4426 if (PropertiesHelper::IsDryRun()) return;
4427 dump_frozen_cgroupfs(CGROUPFS_DIR, 0, _add_file_from_fd);
4428}
4429
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004430void Dumpstate::UpdateProgress(int32_t delta_sec) {
4431 if (progress_ == nullptr) {
4432 MYLOGE("UpdateProgress: progress_ not set\n");
4433 return;
4434 }
Rhed Jaobf63d8a2020-07-21 15:42:55 +08004435 // This function updates progress related members of the dumpstate and reports
4436 // progress percentage to the bugreport client. Since it could be called by
4437 // different dump tasks at the same time if the parallel run is enabled, a
4438 // mutex lock is necessary here to synchronize the call.
4439 std::lock_guard<std::recursive_mutex> lock(mutex_);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004440
4441 // Always update progess so stats can be tuned...
Nandana Dutt402a8392019-06-14 14:25:13 +01004442 progress_->Inc(delta_sec);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004443
4444 // ...but only notifiy listeners when necessary.
4445 if (!options_->do_progress_updates) return;
4446
4447 int progress = progress_->Get();
4448 int max = progress_->GetMax();
Nandana Dutt402a8392019-06-14 14:25:13 +01004449 int percent = 100 * progress / max;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004450
Nandana Dutt402a8392019-06-14 14:25:13 +01004451 if (last_reported_percent_progress_ > 0 && percent <= last_reported_percent_progress_) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004452 return;
4453 }
Nandana Dutt402a8392019-06-14 14:25:13 +01004454 last_reported_percent_progress_ = percent;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004455
4456 if (control_socket_fd_ >= 0) {
4457 dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
4458 fsync(control_socket_fd_);
4459 }
4460
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004461 if (listener_ != nullptr) {
Nandana Dutt235c6672019-11-14 15:22:32 +00004462 if (percent % 10 == 0) {
4463 // We don't want to spam logcat, so only log multiples of 10.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004464 MYLOGD("Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004465 } else {
4466 // stderr is ignored on normal invocations, but useful when calling
4467 // /system/bin/dumpstate directly for debuggging.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004468 fprintf(stderr, "Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004469 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004470
4471 listener_->onProgress(percent);
4472 }
4473}
4474
4475void Dumpstate::TakeScreenshot(const std::string& path) {
4476 const std::string& real_path = path.empty() ? screenshot_path_ : path;
4477 int status =
4478 RunCommand("", {"/system/bin/screencap", "-p", real_path},
4479 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
4480 if (status == 0) {
4481 MYLOGD("Screenshot saved on %s\n", real_path.c_str());
4482 } else {
4483 MYLOGE("Failed to take screenshot on %s\n", real_path.c_str());
4484 }
Paul Chang0d2aad72020-02-13 20:04:03 +08004485 if (listener_ != nullptr) {
4486 // Show a visual indication to indicate screenshot is taken via
4487 // IDumpstateListener.onScreenshotTaken()
4488 listener_->onScreenshotTaken(status == 0);
4489 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004490}
4491
4492bool is_dir(const char* pathname) {
4493 struct stat info;
4494 if (stat(pathname, &info) == -1) {
4495 return false;
4496 }
4497 return S_ISDIR(info.st_mode);
4498}
4499
4500time_t get_mtime(int fd, time_t default_mtime) {
4501 struct stat info;
4502 if (fstat(fd, &info) == -1) {
4503 return default_mtime;
4504 }
4505 return info.st_mtime;
4506}