blob: 5ee6b155f2637e04d9e6445c9365613047346837 [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_";
Andy Hungd62f7e62024-01-11 15:47:52 -0800202static const std::string ANR_TRACE_FILE_PREFIX = "trace_";
Woody Lin20767a92022-11-29 15:50:24 +0800203static const std::string SHUTDOWN_CHECKPOINTS_DIR = "/data/system/shutdown-checkpoints/";
204static const std::string SHUTDOWN_CHECKPOINTS_FILE_PREFIX = "checkpoints-";
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700205
Felipe Lemee844a9d2016-09-21 15:01:39 -0700206// TODO: temporary variables and functions used during C++ refactoring
Nandana Dutt979388e2018-11-30 16:48:55 +0000207
Nandana Dutt5c390032019-03-12 10:52:56 +0000208#define RETURN_IF_USER_DENIED_CONSENT() \
209 if (ds.IsUserConsentDenied()) { \
210 MYLOGE("Returning early as user denied consent to share bugreport with calling app."); \
211 return Dumpstate::RunStatus::USER_CONSENT_DENIED; \
212 }
213
214// Runs func_ptr, but checks user consent before and after running it. Returns USER_CONSENT_DENIED
215// if consent is found to be denied.
216#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(func_ptr, ...) \
217 RETURN_IF_USER_DENIED_CONSENT(); \
218 func_ptr(__VA_ARGS__); \
219 RETURN_IF_USER_DENIED_CONSENT();
220
Rhed Jao5377d792020-07-16 17:37:39 +0800221// Runs func_ptr, and logs a duration report after it's finished.
222#define RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, ...) \
223 { \
224 DurationReporter duration_reporter_in_macro(log_title); \
225 func_ptr(__VA_ARGS__); \
226 }
227
228// Similar with RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK, an additional duration report
229// is output after a slow function is finished.
230#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(log_title, func_ptr, ...) \
231 RETURN_IF_USER_DENIED_CONSENT(); \
232 RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, __VA_ARGS__); \
233 RETURN_IF_USER_DENIED_CONSENT();
234
Chris Morinbc223142022-02-04 14:17:11 -0800235#define WAIT_TASK_WITH_CONSENT_CHECK(future) \
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800236 RETURN_IF_USER_DENIED_CONSENT(); \
Chris Morinbc223142022-02-04 14:17:11 -0800237 WaitForTask(future); \
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800238 RETURN_IF_USER_DENIED_CONSENT();
239
Sahana Raof35ed432019-07-12 10:47:52 +0100240static const char* WAKE_LOCK_NAME = "dumpstate_wakelock";
241
Rhed Jao5377d792020-07-16 17:37:39 +0800242// Names of parallel tasks, they are used for the DumpPool to identify the dump
243// task and the log title of the duration report.
244static const std::string DUMP_TRACES_TASK = "DUMP TRACES";
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800245static const std::string DUMP_INCIDENT_REPORT_TASK = "INCIDENT REPORT";
Aaron Huang24d215d2022-04-27 18:51:16 +0800246static const std::string DUMP_NETSTATS_PROTO_TASK = "DUMP NETSTATS PROTO";
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800247static const std::string DUMP_HALS_TASK = "DUMP HALS";
248static const std::string DUMP_BOARD_TASK = "dumpstate_board()";
Rhed Jaoe017f982020-07-21 17:58:41 +0800249static const std::string DUMP_CHECKINS_TASK = "DUMP CHECKINS";
Kean Mariottica20f2d2023-12-15 09:34:25 +0000250static const std::string SERIALIZE_PERFETTO_TRACE_TASK = "SERIALIZE PERFETTO TRACE";
Rhed Jao5377d792020-07-16 17:37:39 +0800251
Nandana Dutt979388e2018-11-30 16:48:55 +0000252namespace android {
253namespace os {
254namespace {
255
256static int Open(std::string path, int flags, mode_t mode = 0) {
257 int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
258 if (fd == -1) {
259 MYLOGE("open(%s, %s)\n", path.c_str(), strerror(errno));
260 }
261 return fd;
262}
263
mhasank2d75c442020-06-11 15:05:25 -0700264static int OpenForWrite(std::string path) {
265 return Open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
266 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
267}
Nandana Dutt979388e2018-11-30 16:48:55 +0000268
269static int OpenForRead(std::string path) {
270 return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
271}
272
273bool CopyFile(int in_fd, int out_fd) {
274 char buf[4096];
275 ssize_t byte_count;
276 while ((byte_count = TEMP_FAILURE_RETRY(read(in_fd, buf, sizeof(buf)))) > 0) {
277 if (!android::base::WriteFully(out_fd, buf, byte_count)) {
278 return false;
279 }
280 }
281 return (byte_count != -1);
282}
283
284static bool CopyFileToFd(const std::string& input_file, int out_fd) {
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000285 MYLOGD("Going to copy file (%s) to %d\n", input_file.c_str(), out_fd);
Nandana Dutt979388e2018-11-30 16:48:55 +0000286
287 // Obtain a handle to the source file.
288 android::base::unique_fd in_fd(OpenForRead(input_file));
289 if (out_fd != -1 && in_fd.get() != -1) {
290 if (CopyFile(in_fd.get(), out_fd)) {
291 return true;
292 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000293 MYLOGE("Failed to copy file: %s\n", strerror(errno));
Nandana Dutt979388e2018-11-30 16:48:55 +0000294 }
295 return false;
296}
297
Nandana Duttd2f5f082019-01-18 17:13:52 +0000298static bool UnlinkAndLogOnError(const std::string& file) {
Nandana Dutt8ae16e62020-03-27 10:20:22 +0000299 if (file.empty()) {
300 return false;
301 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000302 if (unlink(file.c_str())) {
303 MYLOGE("Failed to unlink file (%s): %s\n", file.c_str(), strerror(errno));
Nandana Duttd2f5f082019-01-18 17:13:52 +0000304 return false;
305 }
306 return true;
307}
Nandana Dutt979388e2018-11-30 16:48:55 +0000308
Nikita Ioffea325a572019-05-16 19:49:47 +0100309int64_t GetModuleMetadataVersion() {
310 auto binder = defaultServiceManager()->getService(android::String16("package_native"));
311 if (binder == nullptr) {
312 MYLOGE("Failed to retrieve package_native service");
313 return 0L;
314 }
315 auto package_service = android::interface_cast<content::pm::IPackageManagerNative>(binder);
316 std::string package_name;
317 auto status = package_service->getModuleMetadataPackageName(&package_name);
318 if (!status.isOk()) {
319 MYLOGE("Failed to retrieve module metadata package name: %s", status.toString8().c_str());
320 return 0L;
321 }
Nandana Duttdb379fa2019-10-09 16:54:41 +0100322 MYLOGD("Module metadata package name: %s\n", package_name.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100323 int64_t version_code;
324 status = package_service->getVersionCodeForPackage(android::String16(package_name.c_str()),
325 &version_code);
326 if (!status.isOk()) {
327 MYLOGE("Failed to retrieve module metadata version: %s", status.toString8().c_str());
328 return 0L;
329 }
330 return version_code;
331}
332
mhasank2d75c442020-06-11 15:05:25 -0700333static bool PathExists(const std::string& path) {
334 struct stat sb;
335 return stat(path.c_str(), &sb) == 0;
336}
337
338static bool CopyFileToFile(const std::string& input_file, const std::string& output_file) {
339 if (input_file == output_file) {
340 MYLOGD("Skipping copying bugreport file since the destination is the same (%s)\n",
341 output_file.c_str());
342 return false;
343 }
344 else if (PathExists(output_file)) {
345 MYLOGD("Cannot overwrite an existing file (%s)\n", output_file.c_str());
346 return false;
347 }
348
349 MYLOGD("Going to copy bugreport file (%s) to %s\n", input_file.c_str(), output_file.c_str());
350 android::base::unique_fd out_fd(OpenForWrite(output_file));
351 return CopyFileToFd(input_file, out_fd.get());
352}
353
Nandana Dutt979388e2018-11-30 16:48:55 +0000354} // namespace
355} // namespace os
356} // namespace android
357
Felipe Leme678727a2016-09-21 17:22:11 -0700358static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
Felipe Lemebda15a02016-11-16 17:48:25 -0800359 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
Rhed Jaoe017f982020-07-21 17:58:41 +0800360 long dumpsysTimeoutMs = 0, int out_fd = STDOUT_FILENO) {
361 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs, out_fd);
362}
363static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
364 int out_fd) {
365 return ds.RunDumpsys(title, dumpsysArgs, Dumpstate::DEFAULT_DUMPSYS, 0, out_fd);
Felipe Leme678727a2016-09-21 17:22:11 -0700366}
367static int DumpFile(const std::string& title, const std::string& path) {
368 return ds.DumpFile(title, path);
369}
Felipe Lemee82a27d2016-01-05 13:35:44 -0800370
Felipe Lemee844a9d2016-09-21 15:01:39 -0700371// Relative directory (inside the zip) for all files copied as-is into the bugreport.
372static const std::string ZIP_ROOT_DIR = "FS";
373
Vishnu Naire97d6122018-01-18 13:58:56 -0800374static const std::string kProtoPath = "proto/";
375static const std::string kProtoExt = ".proto";
Jie Song9fbfad02017-06-20 16:29:42 -0700376static const std::string kDumpstateBoardFiles[] = {
377 "dumpstate_board.txt",
Felipe Leme95d6ca52017-08-01 16:35:56 -0700378 "dumpstate_board.bin"
Jie Song9fbfad02017-06-20 16:29:42 -0700379};
380static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
381
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700382static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Lemed071c682016-10-20 16:48:00 -0700383static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700384
Felipe Lemef0292972016-11-22 13:57:05 -0800385static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
386
Narayan Kamath8f788292017-05-25 13:20:39 +0100387/*
Narayan Kamathbd863722017-06-01 18:50:12 +0100388 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
Rhed Jao01dc0c62020-06-03 17:13:30 +0800389 * The returned vector is sorted by the mtimes of the dumps with descending
Chris Morinc2cba7a2022-02-01 17:06:50 -0800390 * order.
Narayan Kamath8f788292017-05-25 13:20:39 +0100391 */
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700392static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
Chris Morinc2cba7a2022-02-01 17:06:50 -0800393 const std::string& file_prefix) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100394 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100395
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700396 if (dump_dir == nullptr) {
397 MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno));
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700398 return std::vector<DumpData>();
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700399 }
400
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700401 std::vector<DumpData> dump_data;
Narayan Kamathbd863722017-06-01 18:50:12 +0100402 struct dirent* entry = nullptr;
403 while ((entry = readdir(dump_dir.get()))) {
404 if (entry->d_type != DT_REG) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100405 continue;
406 }
407
Narayan Kamathbd863722017-06-01 18:50:12 +0100408 const std::string base_name(entry->d_name);
409 if (base_name.find(file_prefix) != 0) {
410 continue;
411 }
412
413 const std::string abs_path = dir_path + base_name;
414 android::base::unique_fd fd(
415 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
416 if (fd == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700417 MYLOGW("Unable to open dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamathbd863722017-06-01 18:50:12 +0100418 break;
419 }
420
421 struct stat st = {};
422 if (fstat(fd, &st) == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700423 MYLOGW("Unable to stat dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamath8f788292017-05-25 13:20:39 +0100424 continue;
425 }
426
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700427 dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700428 }
Rhed Jao01dc0c62020-06-03 17:13:30 +0800429 if (!dump_data.empty()) {
430 std::sort(dump_data.begin(), dump_data.end(),
431 [](const auto& a, const auto& b) { return a.mtime > b.mtime; });
432 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100433
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700434 return dump_data;
Narayan Kamath8f788292017-05-25 13:20:39 +0100435}
436
Narayan Kamathbd863722017-06-01 18:50:12 +0100437static bool AddDumps(const std::vector<DumpData>::const_iterator start,
438 const std::vector<DumpData>::const_iterator end,
439 const char* type_name, const bool add_to_zip) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100440 bool dumped = false;
Narayan Kamathbd863722017-06-01 18:50:12 +0100441 for (auto it = start; it != end; ++it) {
442 const std::string& name = it->name;
443 const int fd = it->fd;
Narayan Kamath8f788292017-05-25 13:20:39 +0100444 dumped = true;
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100445
446 // Seek to the beginning of the file before dumping any data. A given
447 // DumpData entry might be dumped multiple times in the report.
448 //
449 // For example, the most recent ANR entry is dumped to the body of the
450 // main entry and it also shows up as a separate entry in the bugreport
451 // ZIP file.
452 if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) {
453 MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(),
454 strerror(errno));
455 }
456
Chris Morinc2cba7a2022-02-01 17:06:50 -0800457 if (add_to_zip) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800458 if (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd, /* timeout = */ 0ms) != OK) {
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100459 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100460 }
461 } else {
462 dump_file_from_fd(type_name, name.c_str(), fd);
463 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100464 }
465
466 return dumped;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700467}
468
Felipe Leme635ca312016-01-05 14:23:02 -0800469// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700470void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800471 char path[PATH_MAX];
472
473 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
474 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700475 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800476 char linkname[PATH_MAX];
477 ssize_t r = readlink(path, linkname, PATH_MAX);
478 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800479 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800480 return;
481 }
482 linkname[r] = '\0';
483
484 if (mount_points.find(linkname) == mount_points.end()) {
485 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700486 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700487 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
Felipe Leme635ca312016-01-05 14:23:02 -0800488 mount_points.insert(linkname);
489 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800490 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800491 }
492 }
493}
494
495void add_mountinfo() {
Felipe Leme678727a2016-09-21 17:22:11 -0700496 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800497 mount_points.clear();
Felipe Leme46b85da2016-11-21 17:40:45 -0800498 DurationReporter duration_reporter(title, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700499 for_each_pid(do_mountinfo, nullptr);
500 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800501}
502
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700503static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
504{
505 DIR *d;
506 struct dirent *de;
507 char path[PATH_MAX];
508
509 d = opendir(driverpath);
Yi Kong19d5c002018-07-20 13:39:55 -0700510 if (d == nullptr) {
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700511 return;
512 }
513
514 while ((de = readdir(d))) {
515 if (de->d_type != DT_LNK) {
516 continue;
517 }
518 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700519 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700520 }
521
522 closedir(d);
523}
524
Mark Salyzyn326842f2015-04-30 09:49:41 -0700525static bool skip_not_stat(const char *path) {
526 static const char stat[] = "/stat";
527 size_t len = strlen(path);
528 if (path[len - 1] == '/') { /* Directory? */
529 return false;
530 }
531 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
532}
533
Jeff Sharkey9df29d52023-02-06 14:26:30 -0700534static bool skip_wtf_strictmode(const char *path) {
535 if (strstr(path, "_wtf")) {
536 return true;
537 } else if (strstr(path, "_strictmode")) {
538 return true;
539 }
540 return false;
541}
542
Felipe Leme4c2d6632016-09-28 14:32:00 -0700543static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800544 return false;
545}
546
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700547unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700548
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800549//
550// stat offsets
551// Name units description
552// ---- ----- -----------
553// read I/Os requests number of read I/Os processed
554#define __STAT_READ_IOS 0
555// read merges requests number of read I/Os merged with in-queue I/O
556#define __STAT_READ_MERGES 1
557// read sectors sectors number of sectors read
558#define __STAT_READ_SECTORS 2
559// read ticks milliseconds total wait time for read requests
560#define __STAT_READ_TICKS 3
561// write I/Os requests number of write I/Os processed
562#define __STAT_WRITE_IOS 4
563// write merges requests number of write I/Os merged with in-queue I/O
564#define __STAT_WRITE_MERGES 5
565// write sectors sectors number of sectors written
566#define __STAT_WRITE_SECTORS 6
567// write ticks milliseconds total wait time for write requests
568#define __STAT_WRITE_TICKS 7
569// in_flight requests number of I/Os currently in flight
570#define __STAT_IN_FLIGHT 8
571// io_ticks milliseconds total time this block device has been active
572#define __STAT_IO_TICKS 9
573// time_in_queue milliseconds total wait time for all requests
574#define __STAT_IN_QUEUE 10
575#define __STAT_NUMBER_FIELD 11
576//
577// read I/Os, write I/Os
578// =====================
579//
580// These values increment when an I/O request completes.
581//
582// read merges, write merges
583// =========================
584//
585// These values increment when an I/O request is merged with an
586// already-queued I/O request.
587//
588// read sectors, write sectors
589// ===========================
590//
591// These values count the number of sectors read from or written to this
592// block device. The "sectors" in question are the standard UNIX 512-byte
593// sectors, not any device- or filesystem-specific block size. The
594// counters are incremented when the I/O completes.
595#define SECTOR_SIZE 512
596//
597// read ticks, write ticks
598// =======================
599//
600// These values count the number of milliseconds that I/O requests have
601// waited on this block device. If there are multiple I/O requests waiting,
602// these values will increase at a rate greater than 1000/second; for
603// example, if 60 read requests wait for an average of 30 ms, the read_ticks
604// field will increase by 60*30 = 1800.
605//
606// in_flight
607// =========
608//
609// This value counts the number of I/O requests that have been issued to
610// the device driver but have not yet completed. It does not include I/O
611// requests that are in the queue but not yet issued to the device driver.
612//
613// io_ticks
614// ========
615//
616// This value counts the number of milliseconds during which the device has
617// had I/O requests queued.
618//
619// time_in_queue
620// =============
621//
622// This value counts the number of milliseconds that I/O requests have waited
623// on this block device. If there are multiple I/O requests waiting, this
624// value will increase as the product of the number of milliseconds times the
625// number of requests waiting (see "read ticks" above for an example).
626#define S_TO_MS 1000
627//
628
Mark Salyzyn326842f2015-04-30 09:49:41 -0700629static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800630 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700631 bool z;
Yi Kong19d5c002018-07-20 13:39:55 -0700632 char *cp, *buffer = nullptr;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700633 size_t i = 0;
Josh Gao7c4258c2018-06-25 13:40:08 -0700634 FILE *fp = fdopen(dup(fd), "rb");
Mark Salyzyn326842f2015-04-30 09:49:41 -0700635 getline(&buffer, &i, fp);
636 fclose(fp);
637 if (!buffer) {
638 return -errno;
639 }
640 i = strlen(buffer);
641 while ((i > 0) && (buffer[i - 1] == '\n')) {
642 buffer[--i] = '\0';
643 }
644 if (!*buffer) {
645 free(buffer);
646 return 0;
647 }
648 z = true;
649 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800650 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700651 if (fields[i] != 0) {
652 z = false;
653 }
654 }
655 if (z) { /* never accessed */
656 free(buffer);
657 return 0;
658 }
659
Wei Wang509bb5d2017-06-09 14:42:12 -0700660 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
661 path += sizeof(BLK_DEV_SYS_DIR) - 1;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700662 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700663
664 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
665 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
666 "W-wait", "in-fli", "activ", "T-wait", path, buffer);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700667 free(buffer);
668
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800669 if (fields[__STAT_IO_TICKS]) {
670 unsigned long read_perf = 0;
671 unsigned long read_ios = 0;
672 if (fields[__STAT_READ_TICKS]) {
673 unsigned long long divisor = fields[__STAT_READ_TICKS]
674 * fields[__STAT_IO_TICKS];
675 read_perf = ((unsigned long long)SECTOR_SIZE
676 * fields[__STAT_READ_SECTORS]
677 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
678 / divisor;
679 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
680 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
681 / divisor;
682 }
683
684 unsigned long write_perf = 0;
685 unsigned long write_ios = 0;
686 if (fields[__STAT_WRITE_TICKS]) {
687 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
688 * fields[__STAT_IO_TICKS];
689 write_perf = ((unsigned long long)SECTOR_SIZE
690 * fields[__STAT_WRITE_SECTORS]
691 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
692 / divisor;
693 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
694 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
695 / divisor;
696 }
697
698 unsigned queue = (fields[__STAT_IN_QUEUE]
699 + (fields[__STAT_IO_TICKS] >> 1))
700 / fields[__STAT_IO_TICKS];
701
702 if (!write_perf && !write_ios) {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700703 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 -0800704 } else {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700705 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 -0800706 read_ios, write_perf, write_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800707 }
708
709 /* bugreport timeout factor adjustment */
710 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
711 worst_write_perf = write_perf;
712 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700713 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700714 return 0;
715}
716
Yao Chenbe3bbc12018-01-17 16:31:10 -0800717static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
718
Tom Cherryf4472f32020-08-05 09:31:17 -0700719// Returns the actual readable size of the given buffer or -1 on error.
720static long logcat_buffer_readable_size(const std::string& buffer) {
721 std::unique_ptr<logger_list, decltype(&android_logger_list_free)> logger_list{
722 android_logger_list_alloc(0, 0, 0), &android_logger_list_free};
723 auto logger = android_logger_open(logger_list.get(), android_name_to_log_id(buffer.c_str()));
724
725 return android_logger_get_log_readable_size(logger);
726}
727
728// Returns timeout in ms to read a list of buffers.
Yao Chenbe3bbc12018-01-17 16:31:10 -0800729static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
730 unsigned long timeout_ms = 0;
731 for (const auto& buffer : buffers) {
Tom Cherryf4472f32020-08-05 09:31:17 -0700732 long readable_size = logcat_buffer_readable_size(buffer);
733 if (readable_size > 0) {
734 // Engineering margin is ten-fold our guess.
735 timeout_ms += 10 * (readable_size + worst_write_perf) / worst_write_perf;
736 }
Yao Chenbe3bbc12018-01-17 16:31:10 -0800737 }
738 return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700739}
740
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800741// Opens a socket and returns its file descriptor.
742static int open_socket(const char* service);
743
Nandana Duttd2f5f082019-01-18 17:13:52 +0000744Dumpstate::ConsentCallback::ConsentCallback() : result_(UNAVAILABLE), start_time_(Nanotime()) {
745}
746
747android::binder::Status Dumpstate::ConsentCallback::onReportApproved() {
748 std::lock_guard<std::mutex> lock(lock_);
749 result_ = APPROVED;
750 MYLOGD("User approved consent to share bugreport\n");
Paul Chang0d2aad72020-02-13 20:04:03 +0800751
752 // Maybe copy screenshot so calling app can display the screenshot to the user as soon as
753 // consent is granted.
754 if (ds.options_->is_screenshot_copied) {
755 return android::binder::Status::ok();
756 }
757
758 if (!ds.options_->do_screenshot || ds.options_->screenshot_fd.get() == -1 ||
759 !ds.do_early_screenshot_) {
760 return android::binder::Status::ok();
761 }
762
763 bool copy_succeeded = android::os::CopyFileToFd(ds.screenshot_path_,
764 ds.options_->screenshot_fd.get());
765 ds.options_->is_screenshot_copied = copy_succeeded;
766 if (copy_succeeded) {
767 android::os::UnlinkAndLogOnError(ds.screenshot_path_);
768 }
Nandana Duttd2f5f082019-01-18 17:13:52 +0000769 return android::binder::Status::ok();
770}
771
772android::binder::Status Dumpstate::ConsentCallback::onReportDenied() {
773 std::lock_guard<std::mutex> lock(lock_);
774 result_ = DENIED;
775 MYLOGW("User denied consent to share bugreport\n");
776 return android::binder::Status::ok();
777}
778
779UserConsentResult Dumpstate::ConsentCallback::getResult() {
780 std::lock_guard<std::mutex> lock(lock_);
781 return result_;
782}
783
784uint64_t Dumpstate::ConsentCallback::getElapsedTimeMs() const {
Hunter Knepshieldf0a39052020-01-03 14:53:04 -0800785 return (Nanotime() - start_time_) / NANOS_PER_MILLI;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000786}
787
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700788void Dumpstate::PrintHeader() const {
Mårten Kongstad60195a72022-09-20 14:14:20 +0200789 std::string build, fingerprint, radio, bootloader, network, sdkversion;
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700790 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700791
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700792 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
793 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700794 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
795 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
796 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
Mårten Kongstad60195a72022-09-20 14:14:20 +0200797 sdkversion = android::base::GetProperty("ro.build.version.sdk", "(unknown)");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700798 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
Colin Crossf45fa6b2012-03-26 12:38:26 -0700799
Felipe Lemed8b94e52016-12-08 10:21:44 -0800800 printf("========================================================\n");
801 printf("== dumpstate: %s\n", date);
802 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700803
Felipe Lemed8b94e52016-12-08 10:21:44 -0800804 printf("\n");
805 printf("Build: %s\n", build.c_str());
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700806 // NOTE: fingerprint entry format is important for other tools.
Felipe Lemed8b94e52016-12-08 10:21:44 -0800807 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
808 printf("Bootloader: %s\n", bootloader.c_str());
809 printf("Radio: %s\n", radio.c_str());
810 printf("Network: %s\n", network.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100811 int64_t module_metadata_version = android::os::GetModuleMetadataVersion();
812 if (module_metadata_version != 0) {
813 printf("Module Metadata version: %" PRId64 "\n", module_metadata_version);
814 }
Mårten Kongstad60195a72022-09-20 14:14:20 +0200815 printf("Android SDK version: %s\n", sdkversion.c_str());
816 printf("SDK extensions: ");
817 RunCommandToFd(STDOUT_FILENO, "", {SDK_EXT_INFO, "--header"},
818 CommandOptions::WithTimeout(1).Always().DropRoot().Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700819
Felipe Lemed8b94e52016-12-08 10:21:44 -0800820 printf("Kernel: ");
Felipe Lemef0292972016-11-22 13:57:05 -0800821 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
Felipe Lemed8b94e52016-12-08 10:21:44 -0800822 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
Devin Moore09fde8d2023-03-21 16:28:22 +0000823 printf("Bootconfig: ");
824 DumpFileToFd(STDOUT_FILENO, "", "/proc/bootconfig");
Felipe Leme7709f8a2017-12-05 09:30:09 -0800825 printf("Uptime: ");
826 RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"},
827 CommandOptions::WithTimeout(1).Always().Build());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800828 printf("Bugreport format version: %s\n", version_.c_str());
Kevin Jeonfa64e642023-07-27 11:36:41 -0400829 printf(
830 "Dumpstate info: id=%d pid=%d dry_run=%d parallel_run=%d strict_run=%d args=%s "
831 "bugreport_mode=%s\n",
832 id_, pid_, PropertiesHelper::IsDryRun(), PropertiesHelper::IsParallelRun(),
833 PropertiesHelper::IsStrictRun(), options_->args.c_str(),
834 options_->bugreport_mode_string.c_str());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800835 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800836}
837
Felipe Leme24b66ee2016-06-16 10:55:26 -0700838// List of file extensions that can cause a zip file attachment to be rejected by some email
839// service providers.
840static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
841 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
842 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
843 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
844};
845
Vishnu Naire97d6122018-01-18 13:58:56 -0800846status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd,
847 std::chrono::milliseconds timeout = 0ms) {
Felipe Leme24b66ee2016-06-16 10:55:26 -0700848 std::string valid_name = entry_name;
849
850 // Rename extension if necessary.
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -0700851 size_t idx = entry_name.rfind('.');
Felipe Leme24b66ee2016-06-16 10:55:26 -0700852 if (idx != std::string::npos) {
853 std::string extension = entry_name.substr(idx);
854 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
855 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
856 valid_name = entry_name + ".renamed";
857 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
858 }
859 }
860
Felipe Leme6fe9db62016-02-12 09:04:16 -0800861 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
862 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Kevin Jeon9bbe0ac2022-05-05 22:05:43 +0000863 size_t flags = ZipWriter::kCompress | ZipWriter::kDefaultCompression;
864 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), flags,
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700865 get_mtime(fd, ds.now_));
Felipe Leme1d486fe2016-10-14 18:06:47 -0700866 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700867 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700868 ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800869 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800870 }
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000871 bool finished_entry = false;
872 auto finish_entry = [this, &finished_entry] {
873 if (!finished_entry) {
874 // This should only be called when we're going to return an earlier error,
875 // which would've been logged. This may imply the file is already corrupt
876 // and any further logging from FinishEntry is more likely to mislead than
877 // not.
878 this->zip_writer_->FinishEntry();
879 }
880 };
881 auto scope_guard = android::base::make_scope_guard(finish_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -0800882 auto start = std::chrono::steady_clock::now();
883 auto end = start + timeout;
884 struct pollfd pfd = {fd, POLLIN};
Felipe Lemee82a27d2016-01-05 13:35:44 -0800885
Felipe Leme770410d2016-01-26 17:07:14 -0800886 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800887 while (1) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800888 if (timeout.count() > 0) {
889 // lambda to recalculate the timeout.
890 auto time_left_ms = [end]() {
891 auto now = std::chrono::steady_clock::now();
892 auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
893 return std::max(diff.count(), 0LL);
894 };
895
896 int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
897 if (rc < 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000898 MYLOGE("Error in poll while adding from fd to zip entry %s:%s\n",
899 entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800900 return -errno;
901 } else if (rc == 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000902 MYLOGE("Timed out adding from fd to zip entry %s:%s Timeout:%lldms\n",
Vishnu Naire97d6122018-01-18 13:58:56 -0800903 entry_name.c_str(), strerror(errno), timeout.count());
904 return TIMED_OUT;
905 }
906 }
907
Zach Riggle22200402016-08-18 01:01:24 -0400908 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800909 if (bytes_read == 0) {
910 break;
911 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800912 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800913 return -errno;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800914 }
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700915 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800916 if (err) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700917 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800918 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800919 }
920 }
921
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700922 err = zip_writer_->FinishEntry();
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000923 finished_entry = true;
Felipe Leme1d486fe2016-10-14 18:06:47 -0700924 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700925 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800926 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800927 }
928
Vishnu Naire97d6122018-01-18 13:58:56 -0800929 return OK;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800930}
931
Felipe Leme1d486fe2016-10-14 18:06:47 -0700932bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
933 android::base::unique_fd fd(
934 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700935 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800936 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800937 return false;
938 }
939
Vishnu Naire97d6122018-01-18 13:58:56 -0800940 return (AddZipEntryFromFd(entry_name, fd.get()) == OK);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800941}
942
943/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700944static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800945 return (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) == OK) ? 0 : 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800946}
947
Felipe Leme1d486fe2016-10-14 18:06:47 -0700948void Dumpstate::AddDir(const std::string& dir, bool recursive) {
Felipe Leme678727a2016-09-21 17:22:11 -0700949 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
Felipe Leme46b85da2016-11-21 17:40:45 -0800950 DurationReporter duration_reporter(dir, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700951 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800952}
953
Felipe Leme1d486fe2016-10-14 18:06:47 -0700954bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800955 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Kevin Jeon9bbe0ac2022-05-05 22:05:43 +0000956 size_t flags = ZipWriter::kCompress | ZipWriter::kDefaultCompression;
957 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), flags, ds.now_);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700958 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700959 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700960 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800961 return false;
962 }
963
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700964 err = zip_writer_->WriteBytes(content.c_str(), content.length());
Felipe Leme1d486fe2016-10-14 18:06:47 -0700965 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700966 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700967 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800968 return false;
969 }
970
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700971 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700972 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700973 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800974 return false;
975 }
976
977 return true;
978}
979
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800980static void DoKmsg() {
981 struct stat st;
982 if (!stat(PSTORE_LAST_KMSG, &st)) {
983 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
984 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
985 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
986 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
987 } else {
988 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
989 DumpFile("LAST KMSG", "/proc/last_kmsg");
990 }
991}
992
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800993static void DoKernelLogcat() {
Yao Chenbe3bbc12018-01-17 16:31:10 -0800994 unsigned long timeout_ms = logcat_timeout({"kernel"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800995 RunCommand(
996 "KERNEL LOG",
997 {"logcat", "-b", "kernel", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
998 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
999}
1000
Nandana Duttdb379fa2019-10-09 16:54:41 +01001001static void DoSystemLogcat(time_t since) {
1002 char since_str[80];
1003 strftime(since_str, sizeof(since_str), "%Y-%m-%d %H:%M:%S.000", localtime(&since));
1004
1005 unsigned long timeout_ms = logcat_timeout({"main", "system", "crash"});
1006 RunCommand("SYSTEM LOG",
1007 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v", "-T",
1008 since_str},
1009 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1010}
1011
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001012static void DoRadioLogcat() {
1013 unsigned long timeout_ms = logcat_timeout({"radio"});
1014 RunCommand(
1015 "RADIO LOG",
1016 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1017 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
1018}
1019
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001020static void DoLogcat() {
Vishnu Nair6921f802017-11-22 09:17:23 -08001021 unsigned long timeout_ms;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001022 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
1023 // calculate timeout
Yao Chenbe3bbc12018-01-17 16:31:10 -08001024 timeout_ms = logcat_timeout({"main", "system", "crash"});
Tony Makae737652017-03-30 17:47:09 +01001025 RunCommand("SYSTEM LOG",
Vishnu Nair6921f802017-11-22 09:17:23 -08001026 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1027 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -08001028 timeout_ms = logcat_timeout({"events"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001029 RunCommand(
1030 "EVENT LOG",
1031 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001032 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Yao Chenbe3bbc12018-01-17 16:31:10 -08001033 timeout_ms = logcat_timeout({"stats"});
1034 RunCommand(
1035 "STATS LOG",
1036 {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001037 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001038 DoRadioLogcat();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001039
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001040 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001041 RunCommand("LAST LOGCAT", {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable",
1042 "-v", "uid", "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001043}
1044
Mike Ma5c267872019-08-21 11:31:34 -07001045static void DumpIncidentReport() {
Mike Ma5c267872019-08-21 11:31:34 -07001046 const std::string path = ds.bugreport_internal_dir_ + "/tmp_incident_report";
1047 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1048 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1049 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1050 if (fd < 0) {
1051 MYLOGE("Could not open %s to dump incident report.\n", path.c_str());
1052 return;
1053 }
Kevin Jeonfa64e642023-07-27 11:36:41 -04001054 RunCommandToFd(fd, "", {"incident", "-u"},
1055 CommandOptions::WithTimeout(PropertiesHelper::IsStrictRun() ? 20 : 120).Build());
Mike Ma5c267872019-08-21 11:31:34 -07001056 bool empty = 0 == lseek(fd, 0, SEEK_END);
1057 if (!empty) {
1058 // Use a different name from "incident.proto"
1059 // /proto/incident.proto is reserved for incident service dump
1060 // i.e. metadata for debugging.
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001061 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "incident_report" + kProtoExt,
1062 path);
1063 } else {
1064 unlink(path.c_str());
Mike Ma5c267872019-08-21 11:31:34 -07001065 }
Mike Ma5c267872019-08-21 11:31:34 -07001066}
1067
Aaron Huang24d215d2022-04-27 18:51:16 +08001068static void DumpNetstatsProto() {
1069 const std::string path = ds.bugreport_internal_dir_ + "/tmp_netstats_proto";
1070 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1071 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1072 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1073 if (fd < 0) {
1074 MYLOGE("Could not open %s to dump netstats proto.\n", path.c_str());
1075 return;
1076 }
1077 RunCommandToFd(fd, "", {"dumpsys", "netstats", "--proto"},
Kevin Jeon2fb3dd62022-09-28 18:48:55 +00001078 CommandOptions::WithTimeout(5).Build());
Aaron Huang24d215d2022-04-27 18:51:16 +08001079 bool empty = 0 == lseek(fd, 0, SEEK_END);
1080 if (!empty) {
1081 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "netstats" + kProtoExt,
1082 path);
1083 } else {
1084 unlink(path.c_str());
1085 }
1086}
1087
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001088static void MaybeAddSystemTraceToZip() {
1089 // This function copies into the .zip the system trace that was snapshotted
Kean Mariottica20f2d2023-12-15 09:34:25 +00001090 // by the early call to MaybeSnapshotSystemTraceAsync(), if any background
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001091 // tracing was happening.
Kean Mariotti853b73a2023-07-27 12:40:30 +00001092 bool system_trace_exists = access(SYSTEM_TRACE_SNAPSHOT, F_OK) == 0;
1093 if (!system_trace_exists) {
Kean Mariottica20f2d2023-12-15 09:34:25 +00001094 // No background trace was happening at the time MaybeSnapshotSystemTraceAsync() was invoked
Kean Mariotti853b73a2023-07-27 12:40:30 +00001095 if (!PropertiesHelper::IsUserBuild()) {
1096 MYLOGI(
1097 "No system traces found. Check for previously uploaded traces by looking for "
1098 "go/trace-uuid in logcat")
1099 }
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001100 return;
1101 }
1102 ds.AddZipEntry(
1103 ZIP_ROOT_DIR + SYSTEM_TRACE_SNAPSHOT,
1104 SYSTEM_TRACE_SNAPSHOT);
1105 android::os::UnlinkAndLogOnError(SYSTEM_TRACE_SNAPSHOT);
1106}
1107
Sunny Goyal35949782019-11-19 15:54:36 -08001108static void DumpVisibleWindowViews() {
Sunny Goyal35949782019-11-19 15:54:36 -08001109 DurationReporter duration_reporter("VISIBLE WINDOW VIEWS");
1110 const std::string path = ds.bugreport_internal_dir_ + "/tmp_visible_window_views";
1111 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1112 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1113 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1114 if (fd < 0) {
1115 MYLOGE("Could not open %s to dump visible views.\n", path.c_str());
1116 return;
1117 }
1118 RunCommandToFd(fd, "", {"cmd", "window", "dump-visible-window-views"},
Kevin Jeon774abde2022-09-28 18:20:43 +00001119 CommandOptions::WithTimeout(10).Build());
Sunny Goyal35949782019-11-19 15:54:36 -08001120 bool empty = 0 == lseek(fd, 0, SEEK_END);
1121 if (!empty) {
1122 ds.AddZipEntry("visible_windows.zip", path);
1123 } else {
1124 MYLOGW("Failed to dump visible windows\n");
1125 }
1126 unlink(path.c_str());
1127}
1128
Jayachandran Ca94c7172017-06-10 15:08:12 -07001129static void DumpIpTablesAsRoot() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001130 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
1131 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +09001132 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001133 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +09001134 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
1135 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
1136 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
1137 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001138}
1139
Woody Lin20767a92022-11-29 15:50:24 +08001140static void DumpShutdownCheckpoints() {
1141 const bool shutdown_checkpoints_dumped = AddDumps(
1142 ds.shutdown_checkpoints_.begin(), ds.shutdown_checkpoints_.end(),
1143 "SHUTDOWN CHECKPOINTS", false /* add_to_zip */);
1144 if (!shutdown_checkpoints_dumped) {
1145 printf("*** NO SHUTDOWN CHECKPOINTS to dump in %s\n\n",
1146 SHUTDOWN_CHECKPOINTS_DIR.c_str());
1147 }
1148}
1149
David Andersond9ba4752018-12-11 18:26:59 -08001150static void DumpDynamicPartitionInfo() {
1151 if (!::android::base::GetBoolProperty("ro.boot.dynamic_partitions", false)) {
1152 return;
1153 }
1154
1155 RunCommand("LPDUMP", {"lpdump", "--all"});
David Anderson6650ade2019-10-02 15:18:59 -07001156 RunCommand("DEVICE-MAPPER", {"gsid", "dump-device-mapper"});
David Andersond9ba4752018-12-11 18:26:59 -08001157}
1158
Chris Morin5a50d482022-02-01 17:41:18 -08001159static void AddAnrTraceDir(const std::string& anr_traces_dir) {
Narayan Kamath8f788292017-05-25 13:20:39 +01001160 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
1161 anr_traces_dir.c_str());
1162
1163 // If we're here, dump_traces_path will always be a temporary file
1164 // (created with mkostemp or similar) that contains dumps taken earlier
1165 // on in the process.
1166 if (dump_traces_path != nullptr) {
Chris Morin5a50d482022-02-01 17:41:18 -08001167 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
1168 dump_traces_path);
1169 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
Narayan Kamath8f788292017-05-25 13:20:39 +01001170
1171 const int ret = unlink(dump_traces_path);
1172 if (ret == -1) {
1173 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
1174 strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -07001175 }
1176 }
1177
Narayan Kamathbd863722017-06-01 18:50:12 +01001178 // Add a specific message for the first ANR Dump.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001179 if (ds.anr_data_.size() > 0) {
Chris Morin5a50d482022-02-01 17:41:18 -08001180 // The "last" ANR will always be present in the body of the main entry.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001181 AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1,
Chris Morin5a50d482022-02-01 17:41:18 -08001182 "VM TRACES AT LAST ANR", false /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001183
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001184 // Historical ANRs are always included as separate entries in the bugreport zip file.
Chris Morin5a50d482022-02-01 17:41:18 -08001185 AddDumps(ds.anr_data_.begin(), ds.anr_data_.end(),
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001186 "HISTORICAL ANR", true /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001187 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +01001188 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
1189 }
Andy Hungd62f7e62024-01-11 15:47:52 -08001190
1191 // Add Java anr traces (such as generated by the Finalizer Watchdog).
1192 AddDumps(ds.anr_trace_data_.begin(), ds.anr_trace_data_.end(), "JAVA ANR TRACES",
1193 true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001194}
1195
1196static void AddAnrTraceFiles() {
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001197 std::string anr_traces_dir = "/data/anr";
Narayan Kamath8f788292017-05-25 13:20:39 +01001198
Chris Morin5a50d482022-02-01 17:41:18 -08001199 AddAnrTraceDir(anr_traces_dir);
Narayan Kamath8f788292017-05-25 13:20:39 +01001200
Makoto Onuki83ec63f2019-01-31 17:08:59 -08001201 RunCommand("ANR FILES", {"ls", "-lt", ANR_DIR});
1202
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001203 // Slow traces for slow operations.
Felipe Lemee184f662016-10-27 10:04:47 -07001204 struct stat st;
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001205 int i = 0;
1206 while (true) {
1207 const std::string slow_trace_path =
1208 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
1209 if (stat(slow_trace_path.c_str(), &st)) {
1210 // No traces file at this index, done with the files.
1211 break;
Felipe Lemee184f662016-10-27 10:04:47 -07001212 }
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001213 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
1214 i++;
Felipe Lemee184f662016-10-27 10:04:47 -07001215 }
1216}
1217
Wei Wang509bb5d2017-06-09 14:42:12 -07001218static void DumpBlockStatFiles() {
1219 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -07001220
Wei Wang1dc1ef52017-06-12 11:28:37 -07001221 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
1222
1223 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001224 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1225 return;
1226 }
1227
1228 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -07001229 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001230 if ((d->d_name[0] == '.')
1231 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1232 || (d->d_name[1] == '\0'))) {
1233 continue;
1234 }
1235 const std::string new_path =
1236 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1237 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1238 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1239 printf("\n");
1240 }
Wei Wang1dc1ef52017-06-12 11:28:37 -07001241 return;
Wei Wang509bb5d2017-06-09 14:42:12 -07001242}
Jayachandran Ca94c7172017-06-10 15:08:12 -07001243
1244static void DumpPacketStats() {
1245 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
Jayachandran Ca94c7172017-06-10 15:08:12 -07001246}
1247
1248static void DumpIpAddrAndRules() {
1249 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
Ray Chencbf278a2023-11-20 07:49:45 +00001250 RunCommand("NETWORK INTERFACES", {"ip", "-s", "link"});
Jayachandran Ca94c7172017-06-10 15:08:12 -07001251 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1252 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1253 RunCommand("IP RULES", {"ip", "rule", "show"});
1254 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1255}
1256
Nandana Dutt5c390032019-03-12 10:52:56 +00001257static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, int priority,
1258 std::chrono::milliseconds timeout,
1259 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001260 auto start = std::chrono::steady_clock::now();
Vishnu Naire97d6122018-01-18 13:58:56 -08001261 sp<android::IServiceManager> sm = defaultServiceManager();
1262 Dumpsys dumpsys(sm.get());
Vishnu Naire97d6122018-01-18 13:58:56 -08001263 Vector<String16> args;
1264 Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
Vishnu Naire97d6122018-01-18 13:58:56 -08001265 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1266 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001267 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001268 std::string path(title);
1269 path.append(" - ").append(String8(service).c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -08001270 size_t bytes_written = 0;
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001271 if (PropertiesHelper::IsDryRun()) {
1272 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1273 dumpsys.writeDumpFooter(STDOUT_FILENO, service, std::chrono::milliseconds(1));
1274 } else {
Devin Mooref492c1a2023-03-15 19:19:03 +00001275 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP | Dumpsys::TYPE_PID |
1276 Dumpsys::TYPE_CLIENTS | Dumpsys::TYPE_THREAD,
Devin Mooreae68df22023-02-24 20:59:51 +00001277 service, args);
1278 if (status == OK) {
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001279 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1280 std::chrono::duration<double> elapsed_seconds;
1281 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH &&
1282 service == String16("meminfo")) {
1283 // Use a longer timeout for meminfo, since 30s is not always enough.
1284 status = dumpsys.writeDump(STDOUT_FILENO, service, 60s,
1285 /* as_proto = */ false, elapsed_seconds,
1286 bytes_written);
1287 } else {
1288 status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
1289 /* as_proto = */ false, elapsed_seconds,
1290 bytes_written);
1291 }
1292 dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
1293 bool dump_complete = (status == OK);
1294 dumpsys.stopDumpThread(dump_complete);
Devin Moorecdfa4602023-03-16 20:49:39 +00001295 } else {
1296 MYLOGE("Failed to start dump thread for service: %s, status: %d",
1297 String8(service).c_str(), status);
Gavin Corkeryfac7e2b2021-07-08 22:39:02 +01001298 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001299 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001300
1301 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1302 std::chrono::steady_clock::now() - start);
1303 if (elapsed_duration > timeout) {
1304 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1305 elapsed_duration.count());
1306 break;
1307 }
1308 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001309 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001310}
1311
Vishnu Nair64afc022018-02-01 15:29:34 -08001312static void RunDumpsysText(const std::string& title, int priority,
1313 std::chrono::milliseconds timeout,
1314 std::chrono::milliseconds service_timeout) {
1315 DurationReporter duration_reporter(title);
1316 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1317 fsync(STDOUT_FILENO);
1318 RunDumpsysTextByPriority(title, priority, timeout, service_timeout);
1319}
1320
1321/* Dump all services registered with Normal or Default priority. */
Nandana Dutt5c390032019-03-12 10:52:56 +00001322static Dumpstate::RunStatus RunDumpsysTextNormalPriority(const std::string& title,
1323 std::chrono::milliseconds timeout,
1324 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001325 DurationReporter duration_reporter(title);
1326 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1327 fsync(STDOUT_FILENO);
1328 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout,
1329 service_timeout);
Nandana Dutt5c390032019-03-12 10:52:56 +00001330
1331 RETURN_IF_USER_DENIED_CONSENT();
1332
1333 return RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1334 service_timeout);
Vishnu Nair64afc022018-02-01 15:29:34 -08001335}
1336
Nandana Dutt5c390032019-03-12 10:52:56 +00001337static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priority,
1338 std::chrono::milliseconds timeout,
1339 std::chrono::milliseconds service_timeout) {
Vishnu Naire97d6122018-01-18 13:58:56 -08001340 sp<android::IServiceManager> sm = defaultServiceManager();
1341 Dumpsys dumpsys(sm.get());
1342 Vector<String16> args;
1343 Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
1344 DurationReporter duration_reporter(title);
1345
1346 auto start = std::chrono::steady_clock::now();
1347 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
1348 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001349 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001350 std::string path(kProtoPath);
1351 path.append(String8(service).c_str());
1352 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
1353 path.append("_CRITICAL");
1354 } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
1355 path.append("_HIGH");
1356 }
1357 path.append(kProtoExt);
Steven Morelandcbd69fc2021-07-20 20:45:43 +00001358 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP, service, args);
Vishnu Naire97d6122018-01-18 13:58:56 -08001359 if (status == OK) {
1360 status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
1361 bool dumpTerminated = (status == OK);
1362 dumpsys.stopDumpThread(dumpTerminated);
1363 }
1364 ZipWriter::FileEntry file_entry;
1365 ds.zip_writer_->GetLastEntry(&file_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -08001366
1367 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1368 std::chrono::steady_clock::now() - start);
1369 if (elapsed_duration > timeout) {
1370 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1371 elapsed_duration.count());
1372 break;
1373 }
1374 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001375 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001376}
1377
Nandana Dutta7db6342018-11-21 14:53:34 +00001378// Runs dumpsys on services that must dump first and will take less than 100ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001379static Dumpstate::RunStatus RunDumpsysCritical() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001380 RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1381 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Nandana Dutt5c390032019-03-12 10:52:56 +00001382
1383 RETURN_IF_USER_DENIED_CONSENT();
1384
1385 return RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1386 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Vishnu Nair780b1282017-10-10 13:57:24 -07001387}
1388
1389// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001390static Dumpstate::RunStatus RunDumpsysHigh() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001391 // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
1392 // high priority. Reduce timeout once they are able to dump in a shorter time or
1393 // moved to a parallel task.
1394 RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1395 /* timeout= */ 90s, /* service_timeout= */ 30s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001396
1397 RETURN_IF_USER_DENIED_CONSENT();
1398
1399 return RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1400 /* timeout= */ 5s, /* service_timeout= */ 1s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001401}
1402
1403// Runs dumpsys on services that must dump but can take up to 10s to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001404static Dumpstate::RunStatus RunDumpsysNormal() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001405 RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001406
1407 RETURN_IF_USER_DENIED_CONSENT();
1408
1409 return RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1410 /* timeout= */ 90s, /* service_timeout= */ 10s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001411}
1412
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001413/*
1414 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1415 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1416 * if it's not running in the parallel task.
1417 */
1418static void DumpHals(int out_fd = STDOUT_FILENO) {
Yifan Hong30528a22020-08-07 18:24:06 -07001419 RunCommand("HARDWARE HALS", {"lshal", "--all", "--types=all"},
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001420 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build(),
1421 false, out_fd);
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001422
Steven Moreland44cd9482018-01-04 16:24:13 -08001423 using android::hidl::manager::V1_0::IServiceManager;
1424 using android::hardware::defaultServiceManager;
1425
1426 sp<IServiceManager> sm = defaultServiceManager();
1427 if (sm == nullptr) {
1428 MYLOGE("Could not retrieve hwservicemanager to dump hals.\n");
1429 return;
1430 }
1431
1432 auto ret = sm->list([&](const auto& interfaces) {
1433 for (const std::string& interface : interfaces) {
1434 std::string cleanName = interface;
Steven Morelandc6b1fc22023-07-26 23:53:58 +00001435 std::replace_if(
1436 cleanName.begin(), cleanName.end(),
1437 [](char c) {
1438 return !isalnum(c) && std::string("@-_.").find(c) == std::string::npos;
1439 },
1440 '_');
Nandana Dutt979388e2018-11-30 16:48:55 +00001441 const std::string path = ds.bugreport_internal_dir_ + "/lshal_debug_" + cleanName;
Steven Moreland44cd9482018-01-04 16:24:13 -08001442
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001443 bool empty = false;
Steven Moreland44cd9482018-01-04 16:24:13 -08001444 {
1445 auto fd = android::base::unique_fd(
1446 TEMP_FAILURE_RETRY(open(path.c_str(),
1447 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1448 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1449 if (fd < 0) {
1450 MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str());
1451 continue;
1452 }
1453 RunCommandToFd(fd,
1454 "",
Steven Morelandc81cd3c2018-01-18 14:36:26 -08001455 {"lshal", "debug", "-E", interface},
Steven Moreland44cd9482018-01-04 16:24:13 -08001456 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1457
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001458 empty = 0 == lseek(fd, 0, SEEK_END);
Steven Moreland44cd9482018-01-04 16:24:13 -08001459 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001460 if (!empty) {
1461 ds.EnqueueAddZipEntryAndCleanupIfNeeded("lshal-debug/" + cleanName + ".txt",
1462 path);
1463 } else {
1464 unlink(path.c_str());
1465 }
Steven Moreland44cd9482018-01-04 16:24:13 -08001466 }
1467 });
1468
1469 if (!ret.isOk()) {
1470 MYLOGE("Could not list hals from hwservicemanager.\n");
1471 }
1472}
1473
Devin Moore8df81bb2022-06-08 22:47:02 +00001474// Dump all of the files that make up the vendor interface.
1475// See the files listed in dumpFileList() for the latest list of files.
1476static void DumpVintf() {
Devin Moore16271d92022-09-22 18:28:48 +00001477
1478 const std::string sku = android::base::GetProperty("ro.boot.product.hardware.sku", "");
1479 const auto vintfFiles = android::vintf::details::dumpFileList(sku);
Devin Moore8df81bb2022-06-08 22:47:02 +00001480 for (const auto vintfFile : vintfFiles) {
1481 struct stat st;
1482 if (stat(vintfFile.c_str(), &st) == 0) {
1483 if (S_ISDIR(st.st_mode)) {
1484 ds.AddDir(vintfFile, true /* recursive */);
1485 } else {
1486 ds.EnqueueAddZipEntryAndCleanupIfNeeded(ZIP_ROOT_DIR + vintfFile,
1487 vintfFile);
1488 }
1489 }
1490 }
1491}
1492
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001493static void DumpExternalFragmentationInfo() {
1494 struct stat st;
1495 if (stat("/proc/buddyinfo", &st) != 0) {
1496 MYLOGE("Unable to dump external fragmentation info\n");
1497 return;
1498 }
1499
1500 printf("------ EXTERNAL FRAGMENTATION INFO ------\n");
1501 std::ifstream ifs("/proc/buddyinfo");
1502 auto unusable_index_regex = std::regex{"Node\\s+([0-9]+),\\s+zone\\s+(\\S+)\\s+(.*)"};
1503 for (std::string line; std::getline(ifs, line);) {
1504 std::smatch match_results;
1505 if (std::regex_match(line, match_results, unusable_index_regex)) {
1506 std::stringstream free_pages(std::string{match_results[3]});
1507 std::vector<int> free_pages_per_order(std::istream_iterator<int>{free_pages},
1508 std::istream_iterator<int>());
1509
1510 int total_free_pages = 0;
1511 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1512 total_free_pages += (free_pages_per_order[i] * std::pow(2, i));
1513 }
1514
1515 printf("Node %s, zone %8s", match_results[1].str().c_str(),
1516 match_results[2].str().c_str());
1517
1518 int usable_free_pages = total_free_pages;
1519 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1520 auto unusable_index = (total_free_pages - usable_free_pages) /
1521 static_cast<double>(total_free_pages);
1522 printf(" %5.3f", unusable_index);
1523 usable_free_pages -= (free_pages_per_order[i] * std::pow(2, i));
1524 }
1525
1526 printf("\n");
1527 }
1528 }
1529 printf("\n");
1530}
1531
mhasankd451a472020-05-26 18:02:39 -07001532static void DumpstateLimitedOnly() {
EdenSue8fe4522023-11-20 15:37:23 +08001533 // Trimmed-down version of dumpstate to only include a allowlisted
mhasankd451a472020-05-26 18:02:39 -07001534 // set of logs (system log, event log, and system server / system app
1535 // crashes, and networking logs). See b/136273873 and b/138459828
1536 // for context.
1537 DurationReporter duration_reporter("DUMPSTATE");
1538 unsigned long timeout_ms;
1539 // calculate timeout
1540 timeout_ms = logcat_timeout({"main", "system", "crash"});
1541 RunCommand("SYSTEM LOG",
1542 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1543 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1544 timeout_ms = logcat_timeout({"events"});
1545 RunCommand(
1546 "EVENT LOG",
1547 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1548 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1549
1550 printf("========================================================\n");
1551 printf("== Networking Service\n");
1552 printf("========================================================\n");
1553
1554 RunDumpsys("DUMPSYS NETWORK_SERVICE_LIMITED", {"wifi", "-a"},
1555 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hugo Benichiaa162682020-10-30 23:28:56 +09001556 RunDumpsys("DUMPSYS CONNECTIVITY REQUESTS", {"connectivity", "requests"},
1557 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
mhasankd451a472020-05-26 18:02:39 -07001558
1559 printf("========================================================\n");
1560 printf("== Dropbox crashes\n");
1561 printf("========================================================\n");
1562
1563 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1564 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1565
Bryan Yuefb85d92024-02-02 13:37:06 +00001566
1567 printf("========================================================\n");
1568 printf("== ANR Traces\n");
1569 printf("========================================================\n");
1570
1571 AddAnrTraceFiles();
1572
mhasankd451a472020-05-26 18:02:39 -07001573 printf("========================================================\n");
1574 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1575 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1576 printf("========================================================\n");
1577 printf("== dumpstate: done (id %d)\n", ds.id_);
1578 printf("========================================================\n");
1579}
1580
Rhed Jaoe017f982020-07-21 17:58:41 +08001581/*
1582 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1583 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1584 * if it's not running in the parallel task.
1585 */
1586static void DumpCheckins(int out_fd = STDOUT_FILENO) {
1587 dprintf(out_fd, "========================================================\n");
1588 dprintf(out_fd, "== Checkins\n");
1589 dprintf(out_fd, "========================================================\n");
1590
1591 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"}, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001592 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"}, out_fd);
1593 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"}, out_fd);
1594 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"}, out_fd);
1595 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"}, out_fd);
1596}
1597
1598/*
1599 * Runs dumpsys on activity service to dump all application activities, services
1600 * and providers in the device.
1601 *
1602 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1603 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1604 * if it's not running in the parallel task.
1605 */
1606static void DumpAppInfos(int out_fd = STDOUT_FILENO) {
1607 dprintf(out_fd, "========================================================\n");
1608 dprintf(out_fd, "== Running Application Activities\n");
1609 dprintf(out_fd, "========================================================\n");
1610
1611 // The following dumpsys internally collects output from running apps, so it can take a long
1612 // time. So let's extend the timeout.
1613
1614 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1615
1616 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1617
1618 dprintf(out_fd, "========================================================\n");
1619 dprintf(out_fd, "== Running Application Services (platform)\n");
1620 dprintf(out_fd, "========================================================\n");
1621
1622 RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
1623 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1624
1625 dprintf(out_fd, "========================================================\n");
1626 dprintf(out_fd, "== Running Application Services (non-platform)\n");
1627 dprintf(out_fd, "========================================================\n");
1628
1629 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1630 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1631
1632 dprintf(out_fd, "========================================================\n");
1633 dprintf(out_fd, "== Running Application Providers (platform)\n");
1634 dprintf(out_fd, "========================================================\n");
1635
1636 RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
Rhed Jaob049f182021-01-11 21:08:43 +08001637 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001638
1639 dprintf(out_fd, "========================================================\n");
1640 dprintf(out_fd, "== Running Application Providers (non-platform)\n");
1641 dprintf(out_fd, "========================================================\n");
1642
1643 RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1644 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1645}
1646
Nandana Dutt5c390032019-03-12 10:52:56 +00001647// Dumps various things. Returns early with status USER_CONSENT_DENIED if user denies consent
1648// via the consent they are shown. Ignores other errors that occur while running various
1649// commands. The consent checking is currently done around long running tasks, which happen to
1650// be distributed fairly evenly throughout the function.
Kean Mariotti306633e2022-09-05 16:30:47 +00001651Dumpstate::RunStatus Dumpstate::dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001652 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001653
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001654 // Enqueue slow functions into the thread pool, if the parallel run is enabled.
Aaron Huang24d215d2022-04-27 18:51:16 +08001655 std::future<std::string> dump_hals, dump_incident_report, dump_board, dump_checkins,
Kean Mariottica20f2d2023-12-15 09:34:25 +00001656 dump_netstats_report;
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001657 if (ds.dump_pool_) {
1658 // Pool was shutdown in DumpstateDefaultAfterCritical method in order to
Kean Mariotti306633e2022-09-05 16:30:47 +00001659 // drop root user. Restarts it.
1660 ds.dump_pool_->start(/* thread_counts = */3);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001661
Chris Morinbc223142022-02-04 14:17:11 -08001662 dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
1663 dump_incident_report = ds.dump_pool_->enqueueTask(
1664 DUMP_INCIDENT_REPORT_TASK, &DumpIncidentReport);
Aaron Huang24d215d2022-04-27 18:51:16 +08001665 dump_netstats_report = ds.dump_pool_->enqueueTask(
1666 DUMP_NETSTATS_PROTO_TASK, &DumpNetstatsProto);
Chris Morinbc223142022-02-04 14:17:11 -08001667 dump_board = ds.dump_pool_->enqueueTaskWithFd(
1668 DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
1669 dump_checkins = ds.dump_pool_->enqueueTaskWithFd(DUMP_CHECKINS_TASK, &DumpCheckins, _1);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001670 }
1671
Nandana Dutt5c390032019-03-12 10:52:56 +00001672 // Dump various things. Note that anything that takes "long" (i.e. several seconds) should
1673 // check intermittently (if it's intrerruptable like a foreach on pids) and/or should be wrapped
1674 // in a consent check (via RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK).
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001675 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001676 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001677 DumpBlockStatFiles();
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001678 DumpFile("MEMORY INFO", "/proc/meminfo");
1679 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001680 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001681
Kevin Jeon947922b2022-09-21 00:29:18 +00001682 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "BUGREPORT_PROCDUMP", {"bugreport_procdump"},
1683 CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001684
Sunny Goyal35949782019-11-19 15:54:36 -08001685 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpVisibleWindowViews);
1686
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001687 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1688 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1689 DumpFile("SLAB INFO", "/proc/slabinfo");
1690 DumpFile("ZONEINFO", "/proc/zoneinfo");
1691 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1692 DumpFile("BUDDYINFO", "/proc/buddyinfo");
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001693 DumpExternalFragmentationInfo();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001694
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001695 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001696
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001697 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001698 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001699
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001700 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001701 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_hals));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001702 } else {
1703 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_HALS_TASK, DumpHals);
1704 }
Steven Moreland81b429e2017-01-31 19:50:46 -08001705
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001706 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001707 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001708 struct stat s;
1709 if (stat("/proc/modules", &s) != 0) {
1710 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1711 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001712 RunCommand("LSMOD", {"lsmod"});
Woody Linc198f252021-05-04 16:37:11 +08001713 RunCommand("MODULES INFO",
1714 {"sh", "-c", "cat /proc/modules | cut -d' ' -f1 | "
1715 " while read MOD ; do echo modinfo:$MOD ; modinfo $MOD ; "
1716 "done"}, CommandOptions::AS_ROOT);
Felipe Lemee4eca582016-06-10 17:48:08 -07001717 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001718
Tom Cherryb87dbfa2020-07-28 11:28:53 -07001719 if (android::base::GetBoolProperty("ro.logd.kernel", false)) {
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001720 DoKernelLogcat();
1721 } else {
1722 do_dmesg();
1723 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001724
Devin Moore8df81bb2022-06-08 22:47:02 +00001725 DumpVintf();
1726
Felipe Lemef0292972016-11-22 13:57:05 -08001727 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001728
Jeff Brown1dc94e32014-09-11 14:15:27 -07001729 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001730 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001731
Jack Yu5a6b2e22020-08-14 18:13:35 +08001732 /* Dump Nfc NCI logs */
1733 ds.AddDir("/data/misc/nfc/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001734
Paul Chang0d2aad72020-02-13 20:04:03 +08001735 if (ds.options_->do_screenshot && !ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001736 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001737 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001738 }
1739
Felipe Lemee184f662016-10-27 10:04:47 -07001740 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001741
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001742 MaybeAddSystemTraceToZip();
1743
Narayan Kamath8f788292017-05-25 13:20:39 +01001744 // NOTE: tombstones are always added as separate entries in the zip archive
1745 // and are not interspersed with the main report.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001746 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
Narayan Kamathbd863722017-06-01 18:50:12 +01001747 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001748 if (!tombstones_dumped) {
1749 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001750 }
1751
Jayachandran Ca94c7172017-06-10 15:08:12 -07001752 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001753
Lorenzo Colitti807f2dd2022-05-27 12:48:37 +09001754 RunDumpsys("EBPF MAP STATS", {"connectivity", "trafficcontroller"});
Chenbo Feng276a3b62018-08-07 11:44:49 -07001755
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001756 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001757
Woody Lin20767a92022-11-29 15:50:24 +08001758 DumpShutdownCheckpoints();
1759
Jayachandran Ca94c7172017-06-10 15:08:12 -07001760 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001761
1762 dump_route_tables();
1763
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001764 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1765 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1766 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001767
Nandana Dutt5c390032019-03-12 10:52:56 +00001768 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysHigh);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001769
Chiachang Wang668ede42021-05-17 17:14:20 +08001770 // The dump mechanism in connectivity is refactored due to modularization work. Connectivity can
1771 // only register with a default priority(NORMAL priority). Dumpstate has to call connectivity
1772 // dump with priority parameters to dump high priority information.
1773 RunDumpsys("SERVICE HIGH connectivity", {"connectivity", "--dump-priority", "HIGH"},
1774 CommandOptions::WithTimeout(10).Build());
1775
Elliott Hughes23ccc622017-02-28 10:14:22 -08001776 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001777
Joe Onoratod38bc3a2023-06-29 15:48:28 -07001778 DumpFile("SYSTEM BUILD-TIME RELEASE FLAGS", "/system/etc/build_flags.json");
1779 DumpFile("SYSTEM_EXT BUILD-TIME RELEASE FLAGS", "/system_ext/etc/build_flags.json");
1780 DumpFile("PRODUCT BUILD-TIME RELEASE FLAGS", "/product/etc/build_flags.json");
1781 DumpFile("VENDOR BUILD-TIME RELEASE FLAGS", "/vendor/etc/build_flags.json");
1782
Mårten Kongstad5ad813f2023-09-28 10:09:18 +02001783 RunCommand("ACONFIG FLAGS", {PRINT_FLAGS},
1784 CommandOptions::WithTimeout(10).Always().DropRoot().Build());
Joe Onoratod38bc3a2023-06-29 15:48:28 -07001785
Jin Qianf334d662017-10-10 14:41:37 -07001786 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001787
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001788 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001789
Colin Crossf45fa6b2012-03-26 12:38:26 -07001790 /* Binder state is expensive to look at as it uses a lot of memory. */
Hridya Valsaraju920ba712020-02-09 16:27:01 -08001791 std::string binder_logs_dir = access("/dev/binderfs/binder_logs", R_OK) ?
1792 "/sys/kernel/debug/binder" : "/dev/binderfs/binder_logs";
1793
1794 DumpFile("BINDER FAILED TRANSACTION LOG", binder_logs_dir + "/failed_transaction_log");
1795 DumpFile("BINDER TRANSACTION LOG", binder_logs_dir + "/transaction_log");
1796 DumpFile("BINDER TRANSACTIONS", binder_logs_dir + "/transactions");
1797 DumpFile("BINDER STATS", binder_logs_dir + "/stats");
1798 DumpFile("BINDER STATE", binder_logs_dir + "/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001799
Yifan Hongd90cc652020-02-08 16:52:02 -08001800 ds.AddDir(SNAPSHOTCTL_LOG_DIR, false);
1801
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001802 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001803 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_board));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001804 } else {
1805 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
1806 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001807
Steven Moreland7440ddb2016-12-15 16:13:39 -08001808 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001809 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1810 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001811 // su does not exist on user builds, so try running without it.
1812 // This way any implementations of vril-dump that do not require
1813 // root can run on user builds.
1814 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001815 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001816 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001817 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001818 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001819 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001820 }
1821
Felipe Lemed8b94e52016-12-08 10:21:44 -08001822 printf("========================================================\n");
1823 printf("== Android Framework Services\n");
1824 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001825
Nandana Dutt5c390032019-03-12 10:52:56 +00001826 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001827
Jack He91ff2fe2021-02-18 18:23:43 -08001828 /* Dump Bluetooth HCI logs after getting bluetooth_manager dumpsys */
1829 ds.AddDir("/data/misc/bluetooth/logs", true);
1830
Rhed Jaoe017f982020-07-21 17:58:41 +08001831 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001832 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_checkins));
Rhed Jaoe017f982020-07-21 17:58:41 +08001833 } else {
1834 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_CHECKINS_TASK, DumpCheckins);
1835 }
Dianne Hackborn02bea972013-06-26 18:59:09 -07001836
Rhed Jaoc5f7ec32020-12-22 22:11:08 +08001837 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpAppInfos);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001838
Adrian Roos8b397ab2017-04-04 16:35:44 -07001839 printf("========================================================\n");
1840 printf("== Dropbox crashes\n");
1841 printf("========================================================\n");
1842
1843 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1844 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1845
Felipe Lemed8b94e52016-12-08 10:21:44 -08001846 printf("========================================================\n");
1847 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1848 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1849 printf("========================================================\n");
1850 printf("== dumpstate: done (id %d)\n", ds.id_);
1851 printf("========================================================\n");
Bookatz38472142018-09-28 10:20:24 -07001852
1853 printf("========================================================\n");
1854 printf("== Obtaining statsd metadata\n");
1855 printf("========================================================\n");
1856 // This differs from the usual dumpsys stats, which is the stats report data.
1857 RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
Mike Ma5c267872019-08-21 11:31:34 -07001858
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +09001859 // Add linker configuration directory
1860 ds.AddDir(LINKERCONFIG_DIR, true);
1861
Li Li830179f2022-01-04 12:53:29 -08001862 /* Dump frozen cgroupfs */
1863 dump_frozen_cgroupfs();
Li Li2eedd412021-06-30 15:11:53 -07001864
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001865 if (ds.dump_pool_) {
Aaron Huang24d215d2022-04-27 18:51:16 +08001866 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_netstats_report));
1867 } else {
1868 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_NETSTATS_PROTO_TASK,
1869 DumpNetstatsProto);
1870 }
1871
1872 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001873 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_incident_report));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001874 } else {
1875 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_INCIDENT_REPORT_TASK,
1876 DumpIncidentReport);
1877 }
Mike Ma5c267872019-08-21 11:31:34 -07001878
Kean Mariotti306633e2022-09-05 16:30:47 +00001879 MaybeAddUiTracesToZip();
1880
Nandana Dutt5c390032019-03-12 10:52:56 +00001881 return Dumpstate::RunStatus::OK;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001882}
1883
Nandana Dutt5c390032019-03-12 10:52:56 +00001884/*
1885 * Dumps state for the default case; drops root after it's no longer necessary.
1886 *
1887 * Returns RunStatus::OK if everything went fine.
1888 * Returns RunStatus::ERROR if there was an error.
1889 * Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport
1890 * with the caller.
1891 */
Jichao Lie89d9c12019-11-21 19:02:51 -08001892Dumpstate::RunStatus Dumpstate::DumpstateDefaultAfterCritical() {
Nandana Duttdb379fa2019-10-09 16:54:41 +01001893 // Capture first logcat early on; useful to take a snapshot before dumpstate logs take over the
1894 // buffer.
1895 DoLogcat();
1896 // Capture timestamp after first logcat to use in next logcat
1897 time_t logcat_ts = time(nullptr);
1898
Nandana Dutt4be45d12018-09-26 15:04:23 +01001899 /* collect stack traces from Dalvik and native processes (needs root) */
Chris Morinbc223142022-02-04 14:17:11 -08001900 std::future<std::string> dump_traces;
Rhed Jao5377d792020-07-16 17:37:39 +08001901 if (dump_pool_) {
1902 RETURN_IF_USER_DENIED_CONSENT();
1903 // One thread is enough since we only need to enqueue DumpTraces here.
1904 dump_pool_->start(/* thread_counts = */1);
1905
1906 // DumpTraces takes long time, post it to the another thread in the
1907 // pool, if pool is available
Chris Morinbc223142022-02-04 14:17:11 -08001908 dump_traces = dump_pool_->enqueueTask(
1909 DUMP_TRACES_TASK, &Dumpstate::DumpTraces, &ds, &dump_traces_path);
Rhed Jao5377d792020-07-16 17:37:39 +08001910 } else {
1911 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_TRACES_TASK, ds.DumpTraces,
1912 &dump_traces_path);
1913 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001914
1915 /* Run some operations that require root. */
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001916 if (!PropertiesHelper::IsDryRun()) {
Chris Morinc2cba7a2022-02-01 17:06:50 -08001917 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX);
1918 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX);
Andy Hungd62f7e62024-01-11 15:47:52 -08001919 ds.anr_trace_data_ = GetDumpFds(ANR_DIR, ANR_TRACE_FILE_PREFIX);
Woody Lin20767a92022-11-29 15:50:24 +08001920 ds.shutdown_checkpoints_ = GetDumpFds(
1921 SHUTDOWN_CHECKPOINTS_DIR, SHUTDOWN_CHECKPOINTS_FILE_PREFIX);
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001922 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001923
1924 ds.AddDir(RECOVERY_DIR, true);
1925 ds.AddDir(RECOVERY_DATA_DIR, true);
1926 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
Kelvin Zhang6eaa0f92022-09-12 09:29:19 -07001927 ds.AddDir(UPDATE_ENGINE_PREF_DIR, true);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001928 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1929 if (!PropertiesHelper::IsUserBuild()) {
1930 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1931 ds.AddDir(PROFILE_DATA_DIR_REF, true);
Calin Juravlef84d3692020-04-28 15:31:12 -07001932 ds.AddZipEntry(ZIP_ROOT_DIR + PACKAGE_DEX_USE_LIST, PACKAGE_DEX_USE_LIST);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001933 }
Jerry Changa1df8a92020-01-02 16:03:39 +08001934 ds.AddDir(PREREBOOT_DATA_DIR, false);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001935 add_mountinfo();
Peter Collingbourne78aa2942023-02-15 14:50:31 -08001936 for (const char* path : {"/proc/cpuinfo", "/proc/meminfo"}) {
1937 ds.AddZipEntry(ZIP_ROOT_DIR + path, path);
1938 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001939 DumpIpTablesAsRoot();
David Andersond9ba4752018-12-11 18:26:59 -08001940 DumpDynamicPartitionInfo();
Yifan Hong3945e1b2019-10-29 12:59:23 -07001941 ds.AddDir(OTA_METADATA_DIR, true);
Jeff Sharkey9df29d52023-02-06 14:26:30 -07001942 if (!PropertiesHelper::IsUserBuild()) {
1943 // Include dropbox entry files inside ZIP, but exclude
1944 // noisy WTF and StrictMode entries
1945 dump_files("", DROPBOX_DIR, skip_wtf_strictmode, _add_file_from_fd);
1946 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001947
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001948 // Capture any IPSec policies in play. No keys are exposed here.
Nandana Dutt4be45d12018-09-26 15:04:23 +01001949 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1950
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001951 // Dump IPsec stats. No keys are exposed here.
1952 DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
1953
Nandana Dutt4be45d12018-09-26 15:04:23 +01001954 // Run ss as root so we can see socket marks.
1955 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1956
1957 // Run iotop as root to show top 100 IO threads
1958 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1959
Erick Reyese68df822019-02-11 14:46:36 -08001960 // Gather shared memory buffer info if the product implements it
Hridya Valsaraju1da80c52021-01-09 22:10:11 -08001961 RunCommand("Dmabuf dump", {"dmabuf_dump"});
1962 RunCommand("Dmabuf per-buffer/per-exporter/per-device stats", {"dmabuf_dump", "-b"});
Erick Reyese68df822019-02-11 14:46:36 -08001963
Minchan Kim22c6a1e2019-09-30 15:58:10 -07001964 DumpFile("PSI cpu", "/proc/pressure/cpu");
1965 DumpFile("PSI memory", "/proc/pressure/memory");
1966 DumpFile("PSI io", "/proc/pressure/io");
1967
Steven Moreland9379c462023-12-21 02:04:27 +00001968 ds.AddZipEntry(ZIP_ROOT_DIR + KERNEL_CONFIG, KERNEL_CONFIG);
1969
Mårten Kongstad60195a72022-09-20 14:14:20 +02001970 RunCommand("SDK EXTENSIONS", {SDK_EXT_INFO, "--dump"},
1971 CommandOptions::WithTimeout(10).Always().DropRoot().Build());
1972
Rhed Jao5377d792020-07-16 17:37:39 +08001973 if (dump_pool_) {
1974 RETURN_IF_USER_DENIED_CONSENT();
Chris Morinbc223142022-02-04 14:17:11 -08001975 WaitForTask(std::move(dump_traces));
Rhed Jao5377d792020-07-16 17:37:39 +08001976
Chris Morinbc223142022-02-04 14:17:11 -08001977 // Current running thread in the pool is the root user also. Delete
1978 // the pool and make a new one later to ensure none of threads in the pool are root.
1979 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao5377d792020-07-16 17:37:39 +08001980 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001981 if (!DropRootUser()) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001982 return Dumpstate::RunStatus::ERROR;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001983 }
1984
Nandana Dutt5c390032019-03-12 10:52:56 +00001985 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttdb379fa2019-10-09 16:54:41 +01001986 Dumpstate::RunStatus status = dumpstate();
1987 // Capture logcat since the last time we did it.
1988 DoSystemLogcat(logcat_ts);
1989 return status;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001990}
1991
Rhed Jaob5685b32020-08-14 17:19:17 +08001992// Common states for telephony and wifi which are needed to be collected before
1993// dumpstate drop the root user.
1994static void DumpstateRadioAsRoot() {
1995 DumpIpTablesAsRoot();
1996 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1997}
1998
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001999// This method collects common dumpsys for telephony and wifi. Typically, wifi
2000// reports are fine to include all information, but telephony reports on user
2001// builds need to strip some content (see DumpstateTelephonyOnly).
2002static void DumpstateRadioCommon(bool include_sensitive_info = true) {
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002003 // We need to be picky about some stuff for telephony reports on user builds.
2004 if (!include_sensitive_info) {
2005 // Only dump the radio log buffer (other buffers and dumps contain too much unrelated info).
2006 DoRadioLogcat();
2007 } else {
Rhed Jaob5685b32020-08-14 17:19:17 +08002008 // DumpHals takes long time, post it to the another thread in the pool,
2009 // if pool is available.
Chris Morinbc223142022-02-04 14:17:11 -08002010 std::future<std::string> dump_hals;
Rhed Jaob5685b32020-08-14 17:19:17 +08002011 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002012 dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
Rhed Jaob5685b32020-08-14 17:19:17 +08002013 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002014 // Contains various system properties and process startup info.
2015 do_dmesg();
2016 // Logs other than the radio buffer may contain package/component names and potential PII.
2017 DoLogcat();
2018 // Too broad for connectivity problems.
2019 DoKmsg();
Rhed Jaob5685b32020-08-14 17:19:17 +08002020 // DumpHals contains unrelated hardware info (camera, NFC, biometrics, ...).
2021 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002022 WaitForTask(std::move(dump_hals));
Rhed Jaob5685b32020-08-14 17:19:17 +08002023 } else {
2024 RUN_SLOW_FUNCTION_AND_LOG(DUMP_HALS_TASK, DumpHals);
2025 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002026 }
2027
Jayachandran Ca94c7172017-06-10 15:08:12 -07002028 DumpPacketStats();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002029 DumpIpAddrAndRules();
2030 dump_route_tables();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002031 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
2032 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08002033}
2034
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002035// We use "telephony" here for legacy reasons, though this now really means "connectivity" (cellular
2036// + wifi + networking). This method collects dumpsys for connectivity debugging only. General rules
2037// for what can be included on user builds: all reported information MUST directly relate to
2038// connectivity debugging or customer support and MUST NOT contain unrelated personally identifiable
2039// information. This information MUST NOT identify user-installed packages (UIDs are OK, package
2040// names are not), and MUST NOT contain logs of user application traffic.
2041// TODO(b/148168577) rename this and other related fields/methods to "connectivity" instead.
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08002042static void DumpstateTelephonyOnly(const std::string& calling_package) {
mukesh agrawal253dad42018-01-23 21:59:59 -08002043 DurationReporter duration_reporter("DUMPSTATE");
Jichao Lie89d9c12019-11-21 19:02:51 -08002044
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002045 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
mukesh agrawal253dad42018-01-23 21:59:59 -08002046
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002047 const bool include_sensitive_info = !PropertiesHelper::IsUserBuild();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002048
Rhed Jaob5685b32020-08-14 17:19:17 +08002049 DumpstateRadioAsRoot();
2050 if (!DropRootUser()) {
2051 return;
2052 }
2053
2054 // Starts thread pool after the root user is dropped, and two additional threads
2055 // are created for DumpHals in the DumpstateRadioCommon and DumpstateBoard.
Chris Morinbc223142022-02-04 14:17:11 -08002056 std::future<std::string> dump_board;
Rhed Jaob5685b32020-08-14 17:19:17 +08002057 if (ds.dump_pool_) {
2058 ds.dump_pool_->start(/*thread_counts =*/2);
2059
2060 // DumpstateBoard takes long time, post it to the another thread in the pool,
2061 // if pool is available.
Chris Morinbc223142022-02-04 14:17:11 -08002062 dump_board = ds.dump_pool_->enqueueTaskWithFd(
2063 DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
Rhed Jaob5685b32020-08-14 17:19:17 +08002064 }
2065
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002066 DumpstateRadioCommon(include_sensitive_info);
2067
2068 if (include_sensitive_info) {
2069 // Contains too much unrelated PII, and given the unstructured nature of sysprops, we can't
2070 // really cherrypick all of the connectivity-related ones. Apps generally have no business
2071 // reading these anyway, and there should be APIs to supply the info in a more app-friendly
2072 // way.
2073 RunCommand("SYSTEM PROPERTIES", {"getprop"});
2074 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002075
2076 printf("========================================================\n");
2077 printf("== Android Framework Services\n");
2078 printf("========================================================\n");
2079
Vishnu Nair652cc802017-11-30 15:18:30 -08002080 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2081 SEC_TO_MSEC(10));
Hunter Knepshield31cbae12021-05-11 16:23:24 -07002082 RunDumpsys("DUMPSYS", {"vcn_management"}, CommandOptions::WithTimeout(90).Build(),
2083 SEC_TO_MSEC(10));
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08002084 if (include_sensitive_info) {
2085 // Carrier apps' services will be dumped below in dumpsys activity service all-non-platform.
2086 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
2087 SEC_TO_MSEC(10));
2088 } else {
2089 // If the caller is a carrier app and has a carrier service, dump it here since we aren't
2090 // running dumpsys activity service all-non-platform below. Due to the increased output, we
2091 // give a higher timeout as well.
2092 RunDumpsys("DUMPSYS", {"carrier_config", "--requesting-package", calling_package},
2093 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(30));
2094 }
2095 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002096 RunDumpsys("DUMPSYS", {"netpolicy"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2097 RunDumpsys("DUMPSYS", {"network_management"}, CommandOptions::WithTimeout(90).Build(),
Sooraj Sasindrane8d98912018-04-20 11:31:55 -07002098 SEC_TO_MSEC(10));
Hunter Knepshield0fe51b12020-03-05 16:58:20 -08002099 RunDumpsys("DUMPSYS", {"telephony.registry"}, CommandOptions::WithTimeout(90).Build(),
2100 SEC_TO_MSEC(10));
Jack Yu773cc032023-03-16 22:43:39 -07002101 RunDumpsys("DUMPSYS", {"isub"}, CommandOptions::WithTimeout(90).Build(),
2102 SEC_TO_MSEC(10));
Grant Menke56698972023-02-24 13:11:07 -08002103 RunDumpsys("DUMPSYS", {"telecom"}, CommandOptions::WithTimeout(90).Build(),
2104 SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002105 if (include_sensitive_info) {
2106 // Contains raw IP addresses, omit from reports on user builds.
2107 RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2108 // Contains raw destination IP/MAC addresses, omit from reports on user builds.
2109 RunDumpsys("DUMPSYS", {"connmetrics"}, CommandOptions::WithTimeout(90).Build(),
2110 SEC_TO_MSEC(10));
2111 // Contains package/component names, omit from reports on user builds.
2112 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
2113 SEC_TO_MSEC(10));
2114 // Contains package names, but should be relatively simple to remove them (also contains
2115 // UIDs already), omit from reports on user builds.
2116 RunDumpsys("BATTERYSTATS", {"deviceidle"}, CommandOptions::WithTimeout(90).Build(),
2117 SEC_TO_MSEC(10));
2118 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002119
2120 printf("========================================================\n");
2121 printf("== Running Application Services\n");
2122 printf("========================================================\n");
2123
2124 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
2125
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002126 if (include_sensitive_info) {
2127 printf("========================================================\n");
2128 printf("== Running Application Services (non-platform)\n");
2129 printf("========================================================\n");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002130
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002131 // Contains package/component names and potential PII, omit from reports on user builds.
2132 // To get dumps of the active CarrierService(s) on user builds, we supply an argument to the
2133 // carrier_config dumpsys instead.
2134 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
2135 DUMPSYS_COMPONENTS_OPTIONS);
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002136
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002137 printf("========================================================\n");
2138 printf("== Checkins\n");
2139 printf("========================================================\n");
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002140
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002141 // Contains package/component names, omit from reports on user builds.
2142 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
2143 }
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002144
2145 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07002146 printf("== dumpstate: done (id %d)\n", ds.id_);
2147 printf("========================================================\n");
Rhed Jaob5685b32020-08-14 17:19:17 +08002148
2149 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002150 WaitForTask(std::move(dump_board));
Rhed Jaob5685b32020-08-14 17:19:17 +08002151 } else {
2152 RUN_SLOW_FUNCTION_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
2153 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002154}
2155
mukesh agrawal253dad42018-01-23 21:59:59 -08002156// This method collects dumpsys for wifi debugging only
2157static void DumpstateWifiOnly() {
2158 DurationReporter duration_reporter("DUMPSTATE");
2159
Rhed Jaob5685b32020-08-14 17:19:17 +08002160 DumpstateRadioAsRoot();
2161 if (!DropRootUser()) {
2162 return;
2163 }
2164
2165 // Starts thread pool after the root user is dropped. Only one additional
2166 // thread is needed for DumpHals in the DumpstateRadioCommon.
2167 if (ds.dump_pool_) {
2168 ds.dump_pool_->start(/*thread_counts =*/1);
2169 }
2170
mukesh agrawal253dad42018-01-23 21:59:59 -08002171 DumpstateRadioCommon();
2172
2173 printf("========================================================\n");
2174 printf("== Android Framework Services\n");
2175 printf("========================================================\n");
2176
2177 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2178 SEC_TO_MSEC(10));
2179 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
2180 SEC_TO_MSEC(10));
2181
2182 printf("========================================================\n");
2183 printf("== dumpstate: done (id %d)\n", ds.id_);
2184 printf("========================================================\n");
2185}
2186
Elis Elliott8e401ad2023-08-08 11:18:59 +00002187// Collects a lightweight dumpstate to be used for debugging onboarding related flows.
2188static void DumpstateOnboardingOnly() {
2189 ds.AddDir(LOGPERSIST_DATA_DIR, false);
2190}
2191
Nandana Duttcf419a72019-03-14 10:40:17 +00002192Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
Gavin Corkery789d7a52021-02-24 23:52:35 +00002193 const std::string temp_file_pattern = ds.bugreport_internal_dir_ + "/dumptrace_XXXXXX";
Nandana Duttfaafd522019-03-11 09:23:09 +00002194 const size_t buf_size = temp_file_pattern.length() + 1;
2195 std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
2196 memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
2197
2198 // Create a new, empty file to receive all trace dumps.
2199 //
2200 // TODO: This can be simplified once we remove support for the old style
2201 // dumps. We can have a file descriptor passed in to dump_traces instead
2202 // of creating a file, closing it and then reopening it again.
2203 android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
2204 if (fd < 0) {
2205 MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002206 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002207 }
2208
2209 // Nobody should have access to this temporary file except dumpstate, but we
2210 // temporarily grant 'read' to 'others' here because this file is created
2211 // when tombstoned is still running as root, but dumped after dropping. This
2212 // can go away once support for old style dumping has.
2213 const int chmod_ret = fchmod(fd, 0666);
2214 if (chmod_ret < 0) {
2215 MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002216 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002217 }
2218
2219 std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
2220 if (proc.get() == nullptr) {
2221 MYLOGE("opendir /proc failed: %s\n", strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002222 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002223 }
2224
2225 // Number of times process dumping has timed out. If we encounter too many
2226 // failures, we'll give up.
2227 int timeout_failures = 0;
2228 bool dalvik_found = false;
2229
Jayant Chowdharya0a8eb22022-05-20 03:30:09 +00002230 const std::set<int> hal_pids = get_interesting_pids();
Nandana Duttfaafd522019-03-11 09:23:09 +00002231
2232 struct dirent* d;
2233 while ((d = readdir(proc.get()))) {
Nandana Duttcf419a72019-03-14 10:40:17 +00002234 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttfaafd522019-03-11 09:23:09 +00002235 int pid = atoi(d->d_name);
2236 if (pid <= 0) {
2237 continue;
2238 }
2239
Kevin Jeond0f8a982023-04-07 14:27:11 -04002240 // Skip cached processes.
2241 if (IsCached(pid)) {
2242 // For consistency, the header and footer to this message match those
2243 // dumped by debuggerd in the success case.
2244 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
2245 dprintf(fd, "Dump skipped for cached process.\n");
2246 dprintf(fd, "---- end %d ----", pid);
2247 continue;
2248 }
2249
Nandana Duttfaafd522019-03-11 09:23:09 +00002250 const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
2251 std::string exe;
2252 if (!android::base::Readlink(link_name, &exe)) {
2253 continue;
2254 }
2255
2256 bool is_java_process;
2257 if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
2258 // Don't bother dumping backtraces for the zygote.
2259 if (IsZygote(pid)) {
2260 continue;
2261 }
2262
2263 dalvik_found = true;
2264 is_java_process = true;
2265 } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
2266 is_java_process = false;
2267 } else {
2268 // Probably a native process we don't care about, continue.
2269 continue;
2270 }
2271
2272 // If 3 backtrace dumps fail in a row, consider debuggerd dead.
2273 if (timeout_failures == 3) {
2274 dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
2275 break;
2276 }
2277
2278 const uint64_t start = Nanotime();
2279 const int ret = dump_backtrace_to_file_timeout(
Kevin Jeonb8a39362023-04-04 15:00:34 -04002280 pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace, 3, fd);
Nandana Duttfaafd522019-03-11 09:23:09 +00002281
2282 if (ret == -1) {
2283 // For consistency, the header and footer to this message match those
2284 // dumped by debuggerd in the success case.
2285 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
2286 dprintf(fd, "Dump failed, likely due to a timeout.\n");
2287 dprintf(fd, "---- end %d ----", pid);
2288 timeout_failures++;
2289 continue;
2290 }
2291
2292 // We've successfully dumped stack traces, reset the failure count
2293 // and write a summary of the elapsed time to the file and continue with the
2294 // next process.
2295 timeout_failures = 0;
2296
2297 dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
2298 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
2299 }
2300
2301 if (!dalvik_found) {
2302 MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
2303 }
2304
Nandana Duttcf419a72019-03-14 10:40:17 +00002305 *path = file_name_buf.release();
2306 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002307}
2308
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002309static dumpstate_hal_hidl::DumpstateMode GetDumpstateHalModeHidl(
2310 const Dumpstate::BugreportMode bugreport_mode) {
2311 switch (bugreport_mode) {
2312 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2313 return dumpstate_hal_hidl::DumpstateMode::FULL;
2314 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2315 return dumpstate_hal_hidl::DumpstateMode::INTERACTIVE;
2316 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2317 return dumpstate_hal_hidl::DumpstateMode::REMOTE;
2318 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2319 return dumpstate_hal_hidl::DumpstateMode::WEAR;
2320 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2321 return dumpstate_hal_hidl::DumpstateMode::CONNECTIVITY;
2322 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2323 return dumpstate_hal_hidl::DumpstateMode::WIFI;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002324 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002325 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2326 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2327 }
2328 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2329}
2330
2331static dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode GetDumpstateHalModeAidl(
2332 const Dumpstate::BugreportMode bugreport_mode) {
2333 switch (bugreport_mode) {
2334 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2335 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::FULL;
2336 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2337 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::INTERACTIVE;
2338 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2339 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::REMOTE;
2340 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2341 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WEAR;
2342 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2343 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::CONNECTIVITY;
2344 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2345 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WIFI;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002346 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002347 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2348 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2349 }
2350 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2351}
2352
2353static void DoDumpstateBoardHidl(
2354 const sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_1_0,
2355 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2356 const Dumpstate::BugreportMode bugreport_mode,
2357 const size_t timeout_sec) {
2358
2359 using ScopedNativeHandle =
2360 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
2361 ScopedNativeHandle handle(native_handle_create(static_cast<int>(dumpstate_fds.size()), 0),
2362 [](native_handle_t* handle) {
2363 // we don't close file handle's here
2364 // via native_handle_close(handle)
2365 // instead we let dumpstate_fds close the file handles when
2366 // dumpstate_fds gets destroyed
2367 native_handle_delete(handle);
2368 });
2369 if (handle == nullptr) {
2370 MYLOGE("Could not create native_handle for dumpstate HAL\n");
2371 return;
2372 }
2373
2374 for (size_t i = 0; i < dumpstate_fds.size(); i++) {
2375 handle.get()->data[i] = dumpstate_fds[i].get();
2376 }
2377
2378 // Prefer version 1.1 if available. New devices launching with R are no longer allowed to
2379 // implement just 1.0.
2380 const char* descriptor_to_kill;
2381 using DumpstateBoardTask = std::packaged_task<bool()>;
2382 DumpstateBoardTask dumpstate_board_task;
2383 sp<dumpstate_hal_hidl::IDumpstateDevice> dumpstate_hal(
2384 dumpstate_hal_hidl::IDumpstateDevice::castFrom(dumpstate_hal_1_0));
2385 if (dumpstate_hal != nullptr) {
2386 MYLOGI("Using IDumpstateDevice v1.1 HIDL HAL");
2387
2388 dumpstate_hal_hidl::DumpstateMode dumpstate_hal_mode =
2389 GetDumpstateHalModeHidl(bugreport_mode);
2390
2391 descriptor_to_kill = dumpstate_hal_hidl::IDumpstateDevice::descriptor;
2392 dumpstate_board_task =
2393 DumpstateBoardTask([timeout_sec, dumpstate_hal_mode, dumpstate_hal, &handle]() -> bool {
2394 ::android::hardware::Return<dumpstate_hal_hidl::DumpstateStatus> status =
2395 dumpstate_hal->dumpstateBoard_1_1(handle.get(), dumpstate_hal_mode,
2396 SEC_TO_MSEC(timeout_sec));
2397 if (!status.isOk()) {
2398 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2399 return false;
2400 } else if (status != dumpstate_hal_hidl::DumpstateStatus::OK) {
2401 MYLOGE("dumpstateBoard failed with DumpstateStatus::%s\n",
2402 dumpstate_hal_hidl::toString(status).c_str());
2403 return false;
2404 }
2405 return true;
2406 });
2407 } else {
2408 MYLOGI("Using IDumpstateDevice v1.0 HIDL HAL");
2409
2410 descriptor_to_kill = dumpstate_hal_hidl_1_0::IDumpstateDevice::descriptor;
2411 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal_1_0, &handle]() -> bool {
2412 ::android::hardware::Return<void> status =
2413 dumpstate_hal_1_0->dumpstateBoard(handle.get());
2414 if (!status.isOk()) {
2415 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2416 return false;
2417 }
2418 return true;
2419 });
2420 }
2421 auto result = dumpstate_board_task.get_future();
2422 std::thread(std::move(dumpstate_board_task)).detach();
2423
2424 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2425 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2426 if (!android::base::SetProperty(
2427 "ctl.interface_restart",
2428 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2429 MYLOGE("Couldn't restart dumpstate HAL\n");
2430 }
2431 }
2432 // Wait some time for init to kill dumpstate vendor HAL
2433 constexpr size_t killing_timeout_sec = 10;
2434 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2435 MYLOGE(
2436 "killing dumpstateBoard timed out after %zus, continue and "
2437 "there might be racing in content\n",
2438 killing_timeout_sec);
2439 }
2440}
2441
2442static void DoDumpstateBoardAidl(
2443 const std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal,
2444 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2445 const Dumpstate::BugreportMode bugreport_mode, const size_t timeout_sec) {
2446 MYLOGI("Using IDumpstateDevice AIDL HAL");
2447
2448 const char* descriptor_to_kill;
2449 using DumpstateBoardTask = std::packaged_task<bool()>;
2450 DumpstateBoardTask dumpstate_board_task;
2451 dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode dumpstate_hal_mode =
2452 GetDumpstateHalModeAidl(bugreport_mode);
2453
2454 descriptor_to_kill = dumpstate_hal_aidl::IDumpstateDevice::descriptor;
2455 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal, &dumpstate_fds, dumpstate_hal_mode,
2456 timeout_sec]() -> bool {
2457 auto status = dumpstate_hal->dumpstateBoard(dumpstate_fds, dumpstate_hal_mode, timeout_sec);
2458
2459 if (!status.isOk()) {
2460 MYLOGE("dumpstateBoard failed: %s\n", status.getDescription().c_str());
2461 return false;
2462 }
2463 return true;
2464 });
2465 auto result = dumpstate_board_task.get_future();
2466 std::thread(std::move(dumpstate_board_task)).detach();
2467
2468 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2469 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2470 if (!android::base::SetProperty(
2471 "ctl.interface_restart",
2472 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2473 MYLOGE("Couldn't restart dumpstate HAL\n");
2474 }
2475 }
2476 // Wait some time for init to kill dumpstate vendor HAL
2477 constexpr size_t killing_timeout_sec = 10;
2478 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2479 MYLOGE(
2480 "killing dumpstateBoard timed out after %zus, continue and "
2481 "there might be racing in content\n",
2482 killing_timeout_sec);
2483 }
2484}
2485
2486static std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> GetDumpstateBoardAidlService() {
2487 const std::string aidl_instance_name =
2488 std::string(dumpstate_hal_aidl::IDumpstateDevice::descriptor) + "/default";
2489
2490 if (!AServiceManager_isDeclared(aidl_instance_name.c_str())) {
2491 return nullptr;
2492 }
2493
2494 ndk::SpAIBinder dumpstateBinder(AServiceManager_waitForService(aidl_instance_name.c_str()));
2495
2496 return dumpstate_hal_aidl::IDumpstateDevice::fromBinder(dumpstateBinder);
2497}
2498
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002499void Dumpstate::DumpstateBoard(int out_fd) {
2500 dprintf(out_fd, "========================================================\n");
2501 dprintf(out_fd, "== Board\n");
2502 dprintf(out_fd, "========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08002503
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002504 /*
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002505 * mount debugfs for non-user builds with ro.product.debugfs_restrictions.enabled
Hridya Valsaraju51101602021-04-02 14:32:46 -07002506 * set to true and unmount it after invoking dumpstateBoard_* methods.
2507 * This is to enable debug builds to not have debugfs mounted during runtime.
2508 * It will also ensure that debugfs is only accessed by the dumpstate HAL.
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002509 */
Hridya Valsaraju51101602021-04-02 14:32:46 -07002510 auto mount_debugfs =
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002511 android::base::GetBoolProperty("ro.product.debugfs_restrictions.enabled", false);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002512 if (mount_debugfs) {
2513 RunCommand("mount debugfs", {"mount", "-t", "debugfs", "debugfs", "/sys/kernel/debug"},
2514 AS_ROOT_20);
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002515 RunCommand("chmod debugfs", {"chmod", "0755", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002516 }
2517
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002518 std::vector<std::string> paths;
2519 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07002520 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002521 paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
2522 kDumpstateBoardFiles[i].c_str()));
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002523 remover.emplace_back(android::base::make_scope_guard(
2524 std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002525 }
Jie Song9fbfad02017-06-20 16:29:42 -07002526
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002527 // get dumpstate HAL AIDL implementation
2528 std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal_handle_aidl(
2529 GetDumpstateBoardAidlService());
2530 if (dumpstate_hal_handle_aidl == nullptr) {
2531 MYLOGI("No IDumpstateDevice AIDL implementation\n");
2532 }
2533
2534 // get dumpstate HAL HIDL implementation, only if AIDL HAL implementation not found
2535 sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_handle_hidl_1_0 = nullptr;
2536 if (dumpstate_hal_handle_aidl == nullptr) {
2537 dumpstate_hal_handle_hidl_1_0 = dumpstate_hal_hidl_1_0::IDumpstateDevice::getService();
2538 if (dumpstate_hal_handle_hidl_1_0 == nullptr) {
2539 MYLOGI("No IDumpstateDevice HIDL implementation\n");
2540 }
2541 }
2542
2543 // if neither HIDL nor AIDL implementation found, then return
2544 if (dumpstate_hal_handle_hidl_1_0 == nullptr && dumpstate_hal_handle_aidl == nullptr) {
2545 MYLOGE("Could not find IDumpstateDevice implementation\n");
Wei Wang587eac92018-04-05 12:17:20 -07002546 return;
2547 }
2548
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002549 // this is used to hold the file descriptors and when this variable goes out of scope
2550 // the file descriptors are closed
2551 std::vector<::ndk::ScopedFileDescriptor> dumpstate_fds;
Wei Wang587eac92018-04-05 12:17:20 -07002552
Nandana Dutt5c390032019-03-12 10:52:56 +00002553 // TODO(128270426): Check for consent in between?
Wei Wang587eac92018-04-05 12:17:20 -07002554 for (size_t i = 0; i < paths.size(); i++) {
2555 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
2556
2557 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
2558 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
2559 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
2560 if (fd < 0) {
2561 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
2562 return;
2563 }
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002564
2565 dumpstate_fds.emplace_back(fd.release());
2566 // we call fd.release() here to make sure "fd" does not get closed
2567 // after "fd" goes out of scope after this block.
2568 // "fd" will be closed when "dumpstate_fds" goes out of scope
2569 // i.e. when we exit this function
Wei Wang587eac92018-04-05 12:17:20 -07002570 }
2571
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002572 // Given that bugreport is required to diagnose failures, it's better to set an arbitrary amount
2573 // of timeout for IDumpstateDevice than to block the rest of bugreport. In the timeout case, we
2574 // will kill the HAL and grab whatever it dumped in time.
Michael Eastwood8523ea02022-03-10 16:33:08 -08002575 constexpr size_t timeout_sec = 45;
Wei Wang587eac92018-04-05 12:17:20 -07002576
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002577 if (dumpstate_hal_handle_aidl != nullptr) {
2578 DoDumpstateBoardAidl(dumpstate_hal_handle_aidl, dumpstate_fds, options_->bugreport_mode,
2579 timeout_sec);
2580 } else if (dumpstate_hal_handle_hidl_1_0 != nullptr) {
2581 // run HIDL HAL only if AIDL HAL not found
2582 DoDumpstateBoardHidl(dumpstate_hal_handle_hidl_1_0, dumpstate_fds, options_->bugreport_mode,
2583 timeout_sec);
Wei Wang587eac92018-04-05 12:17:20 -07002584 }
2585
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002586 if (mount_debugfs) {
Hridya Valsaraju51101602021-04-02 14:32:46 -07002587 auto keep_debugfs_mounted =
2588 android::base::GetProperty("persist.dbg.keep_debugfs_mounted", "");
2589 if (keep_debugfs_mounted.empty())
2590 RunCommand("unmount debugfs", {"umount", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002591 }
2592
Wei Wang587eac92018-04-05 12:17:20 -07002593 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
2594 for (size_t i = 0; i < paths.size(); i++) {
2595 struct stat s;
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002596 if (fstat(dumpstate_fds[i].get(), &s) == -1) {
2597 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(), strerror(errno));
Wei Wang587eac92018-04-05 12:17:20 -07002598 file_sizes[i] = -1;
2599 continue;
2600 }
2601 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002602 }
2603
2604 for (size_t i = 0; i < paths.size(); i++) {
2605 if (file_sizes[i] == -1) {
2606 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002607 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002608 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07002609 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002610 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002611 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002612 remover[i].Disable();
2613 EnqueueAddZipEntryAndCleanupIfNeeded(kDumpstateBoardFiles[i], paths[i]);
2614 dprintf(out_fd, "*** See %s entry ***\n", kDumpstateBoardFiles[i].c_str());
Jie Song9fbfad02017-06-20 16:29:42 -07002615 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08002616}
2617
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002618static void ShowUsage() {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002619 fprintf(stderr,
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002620 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o directory] [-p] "
2621 "[-s] [-S] [-q] [-P] [-R] [-L] [-V version]\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002622 " -h: display this help message\n"
2623 " -b: play sound file instead of vibrate, at beginning of job\n"
2624 " -e: play sound file instead of vibrate, at end of job\n"
mhasank2d75c442020-06-11 15:05:25 -07002625 " -o: write to custom directory (only in limited mode)\n"
Abhijeet Kaurbb55a3b2019-06-13 18:07:25 +01002626 " -p: capture screenshot to filename.png\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002627 " -s: write zipped file to control socket (for init)\n"
2628 " -S: write file location to control socket (for init)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002629 " -q: disable vibrate\n"
Abhijeet Kaure370d682019-10-01 16:49:30 +01002630 " -P: send broadcast when started and do progress updates\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002631 " -R: take bugreport in remote mode (shouldn't be used with -P)\n"
Nandana Dutt235864b2019-01-22 12:10:16 +00002632 " -w: start binder service and make it wait for a call to startBugreport\n"
mhasankd451a472020-05-26 18:02:39 -07002633 " -L: output limited information that is safe for submission in feedback reports\n"
Felipe Lemed071c682016-10-20 16:48:00 -07002634 " -v: prints the dumpstate header and exit\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002635}
2636
Wei Liuf87959e2016-08-26 14:51:42 -07002637static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07002638 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07002639}
2640
Felipe Leme1d486fe2016-10-14 18:06:47 -07002641bool Dumpstate::FinishZipFile() {
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002642 // Runs all enqueued adding zip entry and cleanup tasks before finishing the zip file.
2643 if (zip_entry_tasks_) {
2644 zip_entry_tasks_->run(/* do_cancel = */false);
2645 }
2646
Felipe Leme9a523ae2016-10-20 15:10:33 -07002647 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07002648 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07002649 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002650 // Final timestamp
2651 char date[80];
2652 time_t the_real_now_please_stand_up = time(nullptr);
2653 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002654 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002655 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002656
Felipe Leme9a523ae2016-10-20 15:10:33 -07002657 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002658 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08002659 return false;
2660 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07002661 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002662 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08002663 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08002664 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08002665
Felipe Leme0f3fb202016-06-10 17:10:53 -07002666 // Add log file (which contains stderr output) to zip...
2667 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002668 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07002669 MYLOGE("Failed to add dumpstate log to .zip file\n");
2670 return false;
2671 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002672 // TODO: Should truncate the existing file.
2673 // ... and re-open it for further logging.
Nandana Dutta344cb62019-02-22 15:12:35 +00002674 if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
2675 return false;
2676 }
Felipe Leme0f3fb202016-06-10 17:10:53 -07002677 fprintf(stderr, "\n");
2678
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002679 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07002680 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002681 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002682 return false;
2683 }
2684
Felipe Leme1d486fe2016-10-14 18:06:47 -07002685 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
2686 ds.zip_file.reset(nullptr);
2687
Felipe Lemee9d2c542016-11-15 11:48:26 -08002688 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002689 android::os::UnlinkAndLogOnError(tmp_path_);
Felipe Lemec4eee562016-04-21 15:42:55 -07002690
Felipe Leme1e9edc62015-12-21 16:02:13 -08002691 return true;
2692}
Felipe Leme6e01fa62015-11-11 19:35:14 -08002693
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00002694static void SendBroadcast(const std::string& action,
2695 const std::vector<std::string>& args,
2696 int32_t user_id) {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002697 // clang-format off
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00002698 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user",
2699 std::to_string(user_id), "--receiver-foreground",
2700 "--receiver-include-background", "-a", action};
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002701 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08002702
2703 am.insert(am.end(), args.begin(), args.end());
2704
Felipe Leme8d2410e2017-02-08 09:46:08 -08002705 RunCommand("", am,
2706 CommandOptions::WithTimeout(20)
2707 .Log("Sending broadcast: '%s'\n")
2708 .Always()
2709 .DropRoot()
2710 .RedirectStderr()
2711 .Build());
2712}
2713
Felipe Leme35b8cf12017-02-10 15:47:29 -08002714static void Vibrate(int duration_ms) {
2715 // clang-format off
Lais Andrade51156962021-02-22 19:21:35 +00002716 std::vector<std::string> args = {"cmd", "vibrator_manager", "synced", "-f", "-d", "dumpstate",
2717 "oneshot", std::to_string(duration_ms)};
2718 RunCommand("", args,
Felipe Leme35b8cf12017-02-10 15:47:29 -08002719 CommandOptions::WithTimeout(10)
2720 .Log("Vibrate: '%s'\n")
2721 .Always()
2722 .Build());
2723 // clang-format on
2724}
2725
Nandana Dutt979388e2018-11-30 16:48:55 +00002726static void MaybeResolveSymlink(std::string* path) {
2727 std::string resolved_path;
2728 if (android::base::Readlink(*path, &resolved_path)) {
2729 *path = resolved_path;
2730 }
2731}
2732
Nandana Dutt4be45d12018-09-26 15:04:23 +01002733/*
2734 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002735 * and adds the version file. Return false if zip_file could not be open to write.
Nandana Dutt4be45d12018-09-26 15:04:23 +01002736 */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002737static bool PrepareToWriteToFile() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002738 MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2739
Nandana Dutt4be45d12018-09-26 15:04:23 +01002740 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2741 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002742 ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002743 char date[80];
2744 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2745 ds.name_ = date;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002746
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002747 if (ds.options_->telephony_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002748 ds.base_name_ += "-telephony";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002749 } else if (ds.options_->wifi_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002750 ds.base_name_ += "-wifi";
2751 }
2752
Paul Chang0d2aad72020-02-13 20:04:03 +08002753 if (ds.options_->do_screenshot) {
Nandana Dutt9d17b942020-03-26 10:02:59 +00002754 ds.screenshot_path_ = ds.GetPath(ds.CalledByApi() ? "-png.tmp" : ".png");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002755 }
2756 ds.tmp_path_ = ds.GetPath(".tmp");
2757 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2758
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01002759 std::string destination = ds.CalledByApi()
Nandana Dutt54dbd672019-01-11 12:58:05 +00002760 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
Nandana Dutt9a76d202019-01-21 15:56:48 +00002761 : ds.bugreport_internal_dir_.c_str();
Nandana Dutt4be45d12018-09-26 15:04:23 +01002762 MYLOGD(
Nandana Dutt235c6672019-11-14 15:22:32 +00002763 "Bugreport dir: [%s] "
2764 "Base name: [%s] "
2765 "Suffix: [%s] "
2766 "Log path: [%s] "
2767 "Temporary path: [%s] "
2768 "Screenshot path: [%s]\n",
Nandana Dutt9a76d202019-01-21 15:56:48 +00002769 destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2770 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002771
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002772 ds.path_ = ds.GetPath(ds.CalledByApi() ? "-zip.tmp" : ".zip");
2773 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2774 create_parent_dirs(ds.path_.c_str());
2775 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2776 if (ds.zip_file == nullptr) {
2777 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2778 return false;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002779 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002780 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2781 ds.AddTextZipEntry("version.txt", ds.version_);
2782 return true;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002783}
2784
2785/*
Abhijeet Kaure370d682019-10-01 16:49:30 +01002786 * Finalizes writing to the file by zipping the tmp file to the final location,
Nandana Dutt4be45d12018-09-26 15:04:23 +01002787 * printing zipped file status, etc.
2788 */
2789static void FinalizeFile() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002790 bool do_text_file = !ds.FinishZipFile();
2791 if (do_text_file) {
2792 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002793 }
mhasank2d75c442020-06-11 15:05:25 -07002794
2795 std::string final_path = ds.path_;
2796 if (ds.options_->OutputToCustomFile()) {
mhasank3a4cfb42020-06-15 18:06:43 -07002797 final_path = ds.GetPath(ds.options_->out_dir, ".zip");
mhasank2d75c442020-06-11 15:05:25 -07002798 android::os::CopyFileToFile(ds.path_, final_path);
2799 }
2800
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002801 if (ds.options_->stream_to_socket) {
2802 android::os::CopyFileToFd(ds.path_, ds.control_socket_fd_);
2803 } else if (ds.options_->progress_updates_to_socket) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002804 if (do_text_file) {
2805 dprintf(ds.control_socket_fd_,
2806 "FAIL:could not create zip file, check %s "
2807 "for more details\n",
2808 ds.log_path_.c_str());
2809 } else {
mhasank2d75c442020-06-11 15:05:25 -07002810 dprintf(ds.control_socket_fd_, "OK:%s\n", final_path.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002811 }
2812 }
2813}
2814
Nandana Dutt4be45d12018-09-26 15:04:23 +01002815
Nandana Dutt58d72e22018-11-16 10:30:48 +00002816static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2817 switch (mode) {
2818 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2819 return "BUGREPORT_FULL";
2820 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2821 return "BUGREPORT_INTERACTIVE";
2822 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2823 return "BUGREPORT_REMOTE";
2824 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2825 return "BUGREPORT_WEAR";
2826 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2827 return "BUGREPORT_TELEPHONY";
2828 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2829 return "BUGREPORT_WIFI";
Elis Elliott8e401ad2023-08-08 11:18:59 +00002830 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
2831 return "BUGREPORT_ONBOARDING";
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002832 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2833 return "BUGREPORT_DEFAULT";
Nandana Dutt58d72e22018-11-16 10:30:48 +00002834 }
2835}
2836
Steven Leeb573eb82022-11-29 22:31:35 +08002837static bool IsConsentlessBugreportAllowed(const Dumpstate::DumpOptions& options) {
2838 // only BUGREPORT_TELEPHONY does not allow using consentless bugreport
2839 return !options.telephony_only;
2840}
2841
Paul Changf59c2b72020-03-10 02:08:55 +08002842static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options,
2843 bool is_screenshot_requested) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002844 // Modify com.android.shell.BugreportProgressService#isDefaultScreenshotRequired as well for
2845 // default system screenshots.
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002846 options->bugreport_mode = mode;
2847 options->bugreport_mode_string = ModeToString(mode);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002848 switch (mode) {
2849 case Dumpstate::BugreportMode::BUGREPORT_FULL:
Paul Changf59c2b72020-03-10 02:08:55 +08002850 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002851 break;
2852 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002853 // Currently, the dumpstate binder is only used by Shell to update progress.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002854 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002855 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002856 break;
2857 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002858 options->do_vibrate = false;
2859 options->is_remote_mode = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002860 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002861 break;
2862 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
Robert Ginda55ecebd2023-04-03 22:53:13 +00002863 options->do_vibrate = false;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002864 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002865 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002866 break;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002867 // TODO(b/148168577) rename TELEPHONY everywhere to CONNECTIVITY.
Nandana Dutt58d72e22018-11-16 10:30:48 +00002868 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002869 options->telephony_only = true;
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002870 options->do_progress_updates = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002871 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002872 break;
2873 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002874 options->wifi_only = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002875 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002876 break;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002877 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
2878 options->onboarding_only = true;
2879 options->do_screenshot = false;
2880 break;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002881 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2882 break;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002883 }
2884}
2885
Nandana Dutt58d72e22018-11-16 10:30:48 +00002886static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
Nandana Dutt235c6672019-11-14 15:22:32 +00002887 MYLOGI(
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002888 "do_vibrate: %d stream_to_socket: %d progress_updates_to_socket: %d do_screenshot: %d "
Rhed Jao25f50e02020-08-20 00:10:32 +08002889 "is_remote_mode: %d show_header_only: %d telephony_only: %d "
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002890 "wifi_only: %d do_progress_updates: %d fd: %d bugreport_mode: %s "
mhasankd451a472020-05-26 18:02:39 -07002891 "limited_only: %d args: %s\n",
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002892 options.do_vibrate, options.stream_to_socket, options.progress_updates_to_socket,
Paul Chang0d2aad72020-02-13 20:04:03 +08002893 options.do_screenshot, options.is_remote_mode, options.show_header_only,
Rhed Jao25f50e02020-08-20 00:10:32 +08002894 options.telephony_only, options.wifi_only,
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002895 options.do_progress_updates, options.bugreport_fd.get(),
2896 options.bugreport_mode_string.c_str(),
2897 options.limited_only, options.args.c_str());
Nandana Dutt58d72e22018-11-16 10:30:48 +00002898}
2899
Nandana Dutt54dbd672019-01-11 12:58:05 +00002900void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
Kean Mariotti306633e2022-09-05 16:30:47 +00002901 int bugreport_flags,
Nandana Dutt54dbd672019-01-11 12:58:05 +00002902 const android::base::unique_fd& bugreport_fd_in,
Paul Changf59c2b72020-03-10 02:08:55 +08002903 const android::base::unique_fd& screenshot_fd_in,
2904 bool is_screenshot_requested) {
Kean Mariotti306633e2022-09-05 16:30:47 +00002905 this->use_predumped_ui_data = bugreport_flags & BugreportFlag::BUGREPORT_USE_PREDUMPED_UI_DATA;
Gavin Corkerya44686c2022-11-23 18:16:51 +00002906 this->is_consent_deferred = bugreport_flags & BugreportFlag::BUGREPORT_FLAG_DEFER_CONSENT;
Nandana Dutt54dbd672019-01-11 12:58:05 +00002907 // Duplicate the fds because the passed in fds don't outlive the binder transaction.
Todd Frederick621533f2022-03-26 02:54:17 +00002908 bugreport_fd.reset(fcntl(bugreport_fd_in.get(), F_DUPFD_CLOEXEC, 0));
2909 screenshot_fd.reset(fcntl(screenshot_fd_in.get(), F_DUPFD_CLOEXEC, 0));
Nandana Dutt58d72e22018-11-16 10:30:48 +00002910
Paul Changf59c2b72020-03-10 02:08:55 +08002911 SetOptionsFromMode(bugreport_mode, this, is_screenshot_requested);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002912}
2913
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002914Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
2915 RunStatus status = RunStatus::OK;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002916 int c;
mhasankd451a472020-05-26 18:02:39 -07002917 while ((c = getopt(argc, argv, "dho:svqzpLPBRSV:w")) != -1) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002918 switch (c) {
2919 // clang-format off
mhasank3a4cfb42020-06-15 18:06:43 -07002920 case 'o': out_dir = optarg; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002921 case 's': stream_to_socket = true; break;
2922 case 'S': progress_updates_to_socket = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002923 case 'v': show_header_only = true; break;
2924 case 'q': do_vibrate = false; break;
Paul Chang0d2aad72020-02-13 20:04:03 +08002925 case 'p': do_screenshot = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002926 case 'P': do_progress_updates = true; break;
2927 case 'R': is_remote_mode = true; break;
mhasankd451a472020-05-26 18:02:39 -07002928 case 'L': limited_only = true; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002929 case 'V':
2930 case 'd':
2931 case 'z':
2932 // compatibility no-op
2933 break;
Nandana Dutt235864b2019-01-22 12:10:16 +00002934 case 'w':
2935 // This was already processed
2936 break;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002937 case 'h':
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002938 status = RunStatus::HELP;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002939 break;
2940 default:
2941 fprintf(stderr, "Invalid option: %c\n", c);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002942 status = RunStatus::INVALID_INPUT;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002943 break;
2944 // clang-format on
2945 }
2946 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08002947
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002948 for (int i = 0; i < argc; i++) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002949 args += argv[i];
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002950 if (i < argc - 1) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002951 args += " ";
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002952 }
2953 }
2954
2955 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
2956 optind = 1;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002957
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002958 return status;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002959}
2960
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002961bool Dumpstate::DumpOptions::ValidateOptions() const {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002962 if (bugreport_fd.get() != -1 && stream_to_socket) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002963 return false;
2964 }
2965
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002966 if ((progress_updates_to_socket || do_progress_updates) && stream_to_socket) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002967 return false;
2968 }
2969
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002970 if (is_remote_mode && (do_progress_updates || stream_to_socket)) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002971 return false;
2972 }
2973 return true;
2974}
2975
Nandana Dutt197661d2018-11-16 16:40:21 +00002976void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
2977 options_ = std::move(options);
2978}
2979
Abhijeet Kaura407fb82020-03-27 12:51:12 +00002980void Dumpstate::Initialize() {
2981 /* gets the sequential id */
2982 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
2983 id_ = ++last_id;
2984 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
2985}
2986
Nandana Duttd2f5f082019-01-18 17:13:52 +00002987Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
2988 Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
Gavin Corkerya44686c2022-11-23 18:16:51 +00002989 HandleRunStatus(status);
2990 return status;
2991}
2992
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00002993Dumpstate::RunStatus Dumpstate::Retrieve(int32_t calling_uid, const std::string& calling_package,
2994 const bool keep_bugreport_on_retrieval) {
2995 Dumpstate::RunStatus status = RetrieveInternal(calling_uid, calling_package,
2996 keep_bugreport_on_retrieval);
Gavin Corkerya44686c2022-11-23 18:16:51 +00002997 HandleRunStatus(status);
2998 return status;
2999}
3000
3001Dumpstate::RunStatus Dumpstate::RetrieveInternal(int32_t calling_uid,
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003002 const std::string& calling_package,
3003 const bool keep_bugreport_on_retrieval) {
Gavin Corkerya44686c2022-11-23 18:16:51 +00003004 consent_callback_ = new ConsentCallback();
3005 const String16 incidentcompanion("incidentcompanion");
3006 sp<android::IBinder> ics(
3007 defaultServiceManager()->checkService(incidentcompanion));
3008 android::String16 package(calling_package.c_str());
3009 if (ics != nullptr) {
3010 MYLOGD("Checking user consent via incidentcompanion service\n");
3011 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
3012 calling_uid, package, String16(), String16(),
3013 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
3014 } else {
3015 MYLOGD(
3016 "Unable to check user consent; incidentcompanion service unavailable\n");
3017 return RunStatus::USER_CONSENT_TIMED_OUT;
3018 }
3019 UserConsentResult consent_result = consent_callback_->getResult();
3020 int timeout_ms = 30 * 1000;
3021 while (consent_result == UserConsentResult::UNAVAILABLE &&
3022 consent_callback_->getElapsedTimeMs() < timeout_ms) {
3023 sleep(1);
3024 consent_result = consent_callback_->getResult();
3025 }
3026 if (consent_result == UserConsentResult::DENIED) {
3027 return RunStatus::USER_CONSENT_DENIED;
3028 }
3029 if (consent_result == UserConsentResult::UNAVAILABLE) {
3030 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3031 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3032 consent_callback_.get());
3033 return RunStatus::USER_CONSENT_TIMED_OUT;
3034 }
3035
3036 bool copy_succeeded =
3037 android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003038
3039 if (copy_succeeded && (!android::app::admin::flags::onboarding_bugreport_v2_enabled()
3040 || !keep_bugreport_on_retrieval)) {
3041 android::os::UnlinkAndLogOnError(path_);
Gavin Corkerya44686c2022-11-23 18:16:51 +00003042 }
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003043
Gavin Corkerya44686c2022-11-23 18:16:51 +00003044 return copy_succeeded ? Dumpstate::RunStatus::OK
3045 : Dumpstate::RunStatus::ERROR;
3046}
3047
3048void Dumpstate::HandleRunStatus(Dumpstate::RunStatus status) {
3049 if (listener_ != nullptr) {
Nandana Duttbabf6c72019-01-15 14:11:12 +00003050 switch (status) {
3051 case Dumpstate::RunStatus::OK:
Gavin Corkerya44686c2022-11-23 18:16:51 +00003052 listener_->onFinished(path_.c_str());
Nandana Duttbabf6c72019-01-15 14:11:12 +00003053 break;
3054 case Dumpstate::RunStatus::HELP:
3055 break;
3056 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003057 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00003058 break;
3059 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003060 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
3061 break;
3062 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3063 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
3064 break;
3065 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
3066 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00003067 break;
3068 }
3069 }
Nandana Duttbabf6c72019-01-15 14:11:12 +00003070}
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003071void Dumpstate::Cancel() {
3072 CleanupTmpFiles();
3073 android::os::UnlinkAndLogOnError(log_path_);
3074 for (int i = 0; i < NUM_OF_DUMPS; i++) {
3075 android::os::UnlinkAndLogOnError(ds.bugreport_internal_dir_ + "/" +
3076 kDumpstateBoardFiles[i]);
3077 }
3078 tombstone_data_.clear();
3079 anr_data_.clear();
Andy Hungd62f7e62024-01-11 15:47:52 -08003080 anr_trace_data_.clear();
Woody Lin20767a92022-11-29 15:50:24 +08003081 shutdown_checkpoints_.clear();
Rhed Jao0daac912020-08-21 14:48:20 +08003082
3083 // Instead of shutdown the pool, we delete temporary files directly since
3084 // shutdown blocking the call.
3085 if (dump_pool_) {
3086 dump_pool_->deleteTempFiles();
3087 }
3088 if (zip_entry_tasks_) {
3089 zip_entry_tasks_->run(/*do_cancel =*/ true);
3090 }
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003091}
3092
Kean Mariotti306633e2022-09-05 16:30:47 +00003093void Dumpstate::PreDumpUiData() {
Kean Mariottica20f2d2023-12-15 09:34:25 +00003094 auto snapshot_system_trace = MaybeSnapshotSystemTraceAsync();
Kean Mariotti306633e2022-09-05 16:30:47 +00003095 MaybeSnapshotUiTraces();
Kean Mariottica20f2d2023-12-15 09:34:25 +00003096 MaybeWaitForSnapshotSystemTrace(std::move(snapshot_system_trace));
Kean Mariotti306633e2022-09-05 16:30:47 +00003097}
3098
Nandana Dutt979388e2018-11-30 16:48:55 +00003099/*
3100 * Dumps relevant information to a bugreport based on the given options.
3101 *
3102 * The bugreport can be dumped to a file or streamed to a socket.
3103 *
3104 * How dumping to file works:
3105 * stdout is redirected to a temporary file. This will later become the main bugreport entry.
3106 * stderr is redirected a log file.
3107 *
3108 * The temporary bugreport is then populated via printfs, dumping contents of files and
3109 * output of commands to stdout.
3110 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003111 * A bunch of other files and dumps are added to the zip archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00003112 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003113 * The temporary bugreport file and the log file also get added to the archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00003114 *
mhasank2d75c442020-06-11 15:05:25 -07003115 * Bugreports are first generated in a local directory and later copied to the caller's fd
3116 * or directory if supplied.
Nandana Dutt979388e2018-11-30 16:48:55 +00003117 */
Nandana Duttd2f5f082019-01-18 17:13:52 +00003118Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
3119 const std::string& calling_package) {
Rhed Jao5377d792020-07-16 17:37:39 +08003120 DurationReporter duration_reporter("RUN INTERNAL", /* logcat_only = */true);
Nandana Dutt979388e2018-11-30 16:48:55 +00003121 LogDumpOptions(*options_);
Nandana Dutt197661d2018-11-16 16:40:21 +00003122 if (!options_->ValidateOptions()) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00003123 MYLOGE("Invalid options specified\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003124 return RunStatus::INVALID_INPUT;
3125 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003126 /* set as high priority, and protect from OOM killer */
3127 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003128
Felipe Lemed071c682016-10-20 16:48:00 -07003129 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07003130 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003131 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003132 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003133 } else {
3134 /* fallback to kernels <= 2.6.35 */
3135 oom_adj = fopen("/proc/self/oom_adj", "we");
3136 if (oom_adj) {
3137 fputs("-17", oom_adj);
3138 fclose(oom_adj);
3139 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003140 }
3141
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003142 if (version_ == VERSION_DEFAULT) {
3143 version_ = VERSION_CURRENT;
Michal Karpinski4db754f2015-12-11 18:04:32 +00003144 }
3145
Chris Morin5a50d482022-02-01 17:41:18 -08003146 if (version_ != VERSION_CURRENT) {
3147 MYLOGE("invalid version requested ('%s'); supported values are: ('%s', '%s')\n",
3148 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003149 return RunStatus::INVALID_INPUT;
Felipe Lemed071c682016-10-20 16:48:00 -07003150 }
3151
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003152 if (options_->show_header_only) {
3153 PrintHeader();
3154 return RunStatus::OK;
Felipe Lemed071c682016-10-20 16:48:00 -07003155 }
3156
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003157 MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n",
3158 calling_uid, calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003159
Felipe Leme7447d7c2016-11-03 18:12:22 -07003160 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003161 std::string stats_path =
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003162 android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003163 progress_.reset(new Progress(stats_path));
Felipe Leme7447d7c2016-11-03 18:12:22 -07003164
Sahana Raof35ed432019-07-12 10:47:52 +01003165 if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
3166 MYLOGE("Failed to acquire wake lock: %s\n", strerror(errno));
3167 } else {
3168 // Wake lock will be released automatically on process death
3169 MYLOGD("Wake lock acquired.\n");
3170 }
3171
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08003172 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07003173
Felipe Lemef0292972016-11-22 13:57:05 -08003174 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07003175 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
3176 }
3177
Kevin Jeonfa64e642023-07-27 11:36:41 -04003178 if (PropertiesHelper::IsStrictRun()) {
3179 MYLOGI(
3180 "Running on strict-run mode, which has shorter timeouts "
3181 "(to disable, call 'setprop dumpstate.strict_run false')\n");
3182 }
3183
Nandana Dutt235c6672019-11-14 15:22:32 +00003184 MYLOGI("dumpstate info: id=%d, args='%s', bugreport_mode= %s bugreport format version: %s\n",
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00003185 id_, options_->args.c_str(), options_->bugreport_mode_string.c_str(), version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08003186
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003187 do_early_screenshot_ = options_->do_progress_updates;
Felipe Lemee338bf62015-12-07 14:03:50 -08003188
Christopher Ferrised9354f2014-10-01 17:35:01 -07003189 // If we are going to use a socket, do it as early as possible
3190 // to avoid timeouts from bugreport.
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003191 if (options_->stream_to_socket || options_->progress_updates_to_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07003192 MYLOGD("Opening control socket\n");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003193 control_socket_fd_ = open_socket_fn_("dumpstate");
Nandana Dutta344cb62019-02-22 15:12:35 +00003194 if (control_socket_fd_ == -1) {
3195 return ERROR;
3196 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003197 if (options_->progress_updates_to_socket) {
3198 options_->do_progress_updates = 1;
3199 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07003200 }
3201
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003202 if (!PrepareToWriteToFile()) {
3203 return ERROR;
3204 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08003205
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003206 // Interactive, wear & telephony modes are default to true.
3207 // and may enable from cli option or when using control socket
3208 if (options_->do_progress_updates) {
3209 // clang-format off
3210 std::vector<std::string> am_args = {
3211 "--receiver-permission", "android.permission.DUMP",
3212 };
3213 // clang-format on
3214 // Send STARTED broadcast for apps that listen to bugreport generation events
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003215 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED",
3216 am_args, multiuser_get_user_id(calling_uid));
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003217 if (options_->progress_updates_to_socket) {
3218 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08003219 }
3220 }
3221
Nick Kralevichf3599b32016-01-25 15:05:16 -08003222 /* read /proc/cmdline before dropping root */
3223 FILE *cmdline = fopen("/proc/cmdline", "re");
3224 if (cmdline) {
3225 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
3226 fclose(cmdline);
3227 }
3228
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003229 if (options_->do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08003230 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05003231 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003232
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003233 if (zip_file != nullptr) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003234 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
3235 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003236 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08003237 }
3238 }
3239
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003240 int dup_stdout_fd;
3241 int dup_stderr_fd;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003242 // Redirect stderr to log_path_ for debugging.
3243 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
3244 if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
3245 return ERROR;
3246 }
3247 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
3248 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
3249 strerror(errno));
3250 }
Nandana Dutt979388e2018-11-30 16:48:55 +00003251
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003252 // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
3253 // moved into zip file later, if zipping.
3254 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
3255 // TODO: why not write to a file instead of stdout to overcome this problem?
3256 /* TODO: rather than generating a text file now and zipping it later,
3257 it would be more efficient to redirect stdout to the zip entry
3258 directly, but the libziparchive doesn't support that option yet. */
3259 if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
3260 return ERROR;
3261 }
3262 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
3263 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
3264 tmp_path_.c_str(), strerror(errno));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003265 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08003266
3267 // Don't buffer stdout
3268 setvbuf(stdout, nullptr, _IONBF, 0);
3269
Rhed Jao5377d792020-07-16 17:37:39 +08003270 // Enable the parallel run if the client requests to output to a file.
3271 EnableParallelRunIfNeeded();
3272 // Using scope guard to make sure the dump pool can be shut down correctly.
3273 auto scope_guard_to_shutdown_pool = android::base::make_scope_guard([=]() {
3274 ShutdownDumpPool();
3275 });
3276
Felipe Leme608385d2016-02-01 10:35:38 -08003277 // NOTE: there should be no stdout output until now, otherwise it would break the header.
3278 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08003279 // duration is logged into MYLOG instead.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003280 PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003281
Kean Mariottica20f2d2023-12-15 09:34:25 +00003282 std::future<std::string> snapshot_system_trace;
3283
Kean Mariotti853b73a2023-07-27 12:40:30 +00003284 bool is_dumpstate_restricted =
3285 options_->telephony_only || options_->wifi_only || options_->limited_only;
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003286 if (!is_dumpstate_restricted) {
3287 // Snapshot the system trace now (if running) to avoid that dumpstate's
3288 // own activity pushes out interesting data from the trace ring buffer.
3289 // The trace file is added to the zip by MaybeAddSystemTraceToZip().
Kean Mariottica20f2d2023-12-15 09:34:25 +00003290 snapshot_system_trace = MaybeSnapshotSystemTraceAsync();
Yohei Yukawa95305b32021-03-09 07:54:27 -08003291
Kean Mariotti853b73a2023-07-27 12:40:30 +00003292 // Invoke critical dumpsys to preserve system state, before doing anything else.
3293 RunDumpsysCritical();
3294
Kean Mariotti306633e2022-09-05 16:30:47 +00003295 // Snapshot the UI traces now (if running).
3296 // The trace files will be added to bugreport later.
3297 MaybeSnapshotUiTraces();
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003298 }
Kean Mariotti853b73a2023-07-27 12:40:30 +00003299
3300 MaybeTakeEarlyScreenshot();
Kean Mariottica20f2d2023-12-15 09:34:25 +00003301 MaybeWaitForSnapshotSystemTrace(std::move(snapshot_system_trace));
Gavin Corkery6968f552020-11-22 18:09:05 +00003302 onUiIntensiveBugreportDumpsFinished(calling_uid);
3303 MaybeCheckUserConsent(calling_uid, calling_package);
3304 if (options_->telephony_only) {
3305 DumpstateTelephonyOnly(calling_package);
3306 } else if (options_->wifi_only) {
3307 DumpstateWifiOnly();
3308 } else if (options_->limited_only) {
3309 DumpstateLimitedOnly();
Elis Elliott8e401ad2023-08-08 11:18:59 +00003310 } else if (options_->onboarding_only) {
3311 DumpstateOnboardingOnly();
Gavin Corkery6968f552020-11-22 18:09:05 +00003312 } else {
Nandana Dutt4be45d12018-09-26 15:04:23 +01003313 // Dump state for the default case. This also drops root.
Jichao Lie89d9c12019-11-21 19:02:51 -08003314 RunStatus s = DumpstateDefaultAfterCritical();
Nandana Dutt5c390032019-03-12 10:52:56 +00003315 if (s != RunStatus::OK) {
Nandana Duttaac6f582019-07-26 14:32:47 +01003316 if (s == RunStatus::USER_CONSENT_DENIED) {
Nandana Dutt5c390032019-03-12 10:52:56 +00003317 HandleUserConsentDenied();
3318 }
3319 return s;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08003320 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07003321 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07003322
Felipe Leme55b42a62015-11-10 17:39:08 -08003323 /* close output if needed */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003324 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003325
Abhijeet Kaure370d682019-10-01 16:49:30 +01003326 // Zip the (now complete) .tmp file within the internal directory.
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003327 ATRACE_BEGIN("FinalizeFile");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003328 FinalizeFile();
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003329 ATRACE_END();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003330
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003331 // Share the final file with the caller if the user has consented or Shell is the caller.
Nandana Duttd2f5f082019-01-18 17:13:52 +00003332 Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
Gavin Corkerya44686c2022-11-23 18:16:51 +00003333 if (CalledByApi() && !options_->is_consent_deferred) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003334 status = CopyBugreportIfUserConsented(calling_uid);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003335 if (status != Dumpstate::RunStatus::OK &&
3336 status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3337 // Do an early return if there were errors. We make an exception for consent
3338 // timing out because it's possible the user got distracted. In this case the
3339 // bugreport is not shared but made available for manual retrieval.
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003340 MYLOGI("User denied consent. Returning\n");
Nandana Duttd2f5f082019-01-18 17:13:52 +00003341 return status;
3342 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003343 if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3344 MYLOGI(
3345 "Did not receive user consent yet."
3346 " Will not copy the bugreport artifacts to caller.\n");
Abhijeet Kaur57627412019-04-17 16:00:09 +01003347 const String16 incidentcompanion("incidentcompanion");
3348 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
3349 if (ics != nullptr) {
3350 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3351 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3352 consent_callback_.get());
3353 } else {
3354 MYLOGD("Unable to cancel user consent; incidentcompanion service unavailable\n");
3355 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003356 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003357 }
3358
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003359 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003360 if (options_->do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09003361 for (int i = 0; i < 3; i++) {
3362 Vibrate(75);
3363 usleep((75 + 50) * 1000);
3364 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003365 }
3366
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003367 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
3368 progress_->GetInitialMax());
3369 progress_->Save();
3370 MYLOGI("done (id %d)\n", id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003371
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003372 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08003373
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003374 if (control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07003375 MYLOGD("Closing control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003376 close(control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07003377 }
3378
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003379 tombstone_data_.clear();
3380 anr_data_.clear();
Andy Hungd62f7e62024-01-11 15:47:52 -08003381 anr_trace_data_.clear();
Woody Lin20767a92022-11-29 15:50:24 +08003382 shutdown_checkpoints_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01003383
Nandana Duttd2f5f082019-01-18 17:13:52 +00003384 return (consent_callback_ != nullptr &&
3385 consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
3386 ? USER_CONSENT_TIMED_OUT
3387 : RunStatus::OK;
3388}
3389
Paul Chang0d2aad72020-02-13 20:04:03 +08003390void Dumpstate::MaybeTakeEarlyScreenshot() {
3391 if (!options_->do_screenshot || !do_early_screenshot_) {
3392 return;
3393 }
3394
3395 TakeScreenshot();
3396}
3397
Kean Mariottica20f2d2023-12-15 09:34:25 +00003398std::future<std::string> Dumpstate::MaybeSnapshotSystemTraceAsync() {
Kean Mariotti853b73a2023-07-27 12:40:30 +00003399 // When capturing traces via bugreport handler (BH), this function will be invoked twice:
3400 // 1) When BH invokes IDumpstate::PreDumpUiData()
3401 // 2) When BH invokes IDumpstate::startBugreport(flags = BUGREPORT_USE_PREDUMPED_UI_DATA)
3402 // In this case we don't want to re-invoke perfetto in step 2.
3403 // In all other standard invocation states, this function is invoked once
3404 // without the flag BUGREPORT_USE_PREDUMPED_UI_DATA.
Kean Mariottica20f2d2023-12-15 09:34:25 +00003405 // This function must run asynchronously to avoid delaying MaybeTakeEarlyScreenshot() in the
3406 // standard invocation states (b/316110955).
Kean Mariotti853b73a2023-07-27 12:40:30 +00003407 if (options_->use_predumped_ui_data) {
Kean Mariottica20f2d2023-12-15 09:34:25 +00003408 return {};
3409 }
3410
3411 // Create temporary file for the command's output
3412 std::string outPath = ds.bugreport_internal_dir_ + "/tmp_serialize_perfetto_trace";
3413 auto outFd = android::base::unique_fd(TEMP_FAILURE_RETRY(
3414 open(outPath.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
3415 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
3416 if (outFd < 0) {
3417 MYLOGE("Could not open %s to serialize perfetto trace.\n", outPath.c_str());
3418 return {};
Kean Mariotti853b73a2023-07-27 12:40:30 +00003419 }
3420
3421 // If a stale file exists already, remove it.
3422 unlink(SYSTEM_TRACE_SNAPSHOT);
3423
Kean Mariottica20f2d2023-12-15 09:34:25 +00003424 MYLOGI("Launching async '%s'", SERIALIZE_PERFETTO_TRACE_TASK.c_str())
3425 return std::async(
3426 std::launch::async, [this, outPath = std::move(outPath), outFd = std::move(outFd)] {
3427 // If a background system trace is happening and is marked as "suitable for
3428 // bugreport" (i.e. bugreport_score > 0 in the trace config), this command
3429 // will stop it and serialize into SYSTEM_TRACE_SNAPSHOT. In the (likely)
3430 // case that no trace is ongoing, this command is a no-op.
3431 // Note: this should not be enqueued as we need to freeze the trace before
3432 // dumpstate starts. Otherwise the trace ring buffers will contain mostly
3433 // the dumpstate's own activity which is irrelevant.
3434 RunCommand(
3435 SERIALIZE_PERFETTO_TRACE_TASK, {"perfetto", "--save-for-bugreport"},
3436 CommandOptions::WithTimeout(10).DropRoot().CloseAllFileDescriptorsOnExec().Build(),
3437 false, outFd);
3438 // MaybeAddSystemTraceToZip() will take care of copying the trace in the zip
3439 // file in the later stages.
3440
3441 return outPath;
3442 });
3443}
3444
3445void Dumpstate::MaybeWaitForSnapshotSystemTrace(std::future<std::string> task) {
3446 if (!task.valid()) {
3447 return;
3448 }
3449
3450 WaitForTask(std::move(task), SERIALIZE_PERFETTO_TRACE_TASK, STDOUT_FILENO);
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003451}
3452
Kean Mariotti306633e2022-09-05 16:30:47 +00003453void Dumpstate::MaybeSnapshotUiTraces() {
3454 if (PropertiesHelper::IsUserBuild() || options_->use_predumped_ui_data) {
3455 return;
3456 }
3457
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003458 const std::vector<std::vector<std::string>> dumpTracesForBugReportCommands = {
3459 {"dumpsys", "activity", "service", "SystemUIService", "WMShell", "protolog",
3460 "save-for-bugreport"},
3461 {"dumpsys", "activity", "service", "SystemUIService", "WMShell", "transitions", "tracing",
3462 "save-for-bugreport"},
3463 {"cmd", "input_method", "tracing", "save-for-bugreport"},
3464 {"cmd", "window", "tracing", "save-for-bugreport"},
3465 {"cmd", "window", "shell", "tracing", "save-for-bugreport"},
3466 };
Hongwei Wang39229132023-01-24 15:09:59 -08003467
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003468 for (const auto& command : dumpTracesForBugReportCommands) {
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003469 RunCommand(
3470 // Empty name because it's not intended to be classified as a bugreport section.
3471 // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003472 "", command,
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003473 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
3474 }
Kean Mariotti306633e2022-09-05 16:30:47 +00003475}
3476
3477void Dumpstate::MaybeAddUiTracesToZip() {
3478 if (PropertiesHelper::IsUserBuild()) {
3479 return;
3480 }
3481
3482 ds.AddDir(WMTRACE_DATA_DIR, false);
Yohei Yukawa95305b32021-03-09 07:54:27 -08003483}
3484
Paul Changeb4b4642020-05-28 22:05:47 +08003485void Dumpstate::onUiIntensiveBugreportDumpsFinished(int32_t calling_uid) {
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003486 if (multiuser_get_app_id(calling_uid) == AID_SHELL || !CalledByApi()) {
Paul Changc490e662020-04-11 18:14:09 +08003487 return;
3488 }
3489 if (listener_ != nullptr) {
3490 // Let listener know ui intensive bugreport dumps are finished, then it can do event
3491 // handling if required.
Paul Changeb4b4642020-05-28 22:05:47 +08003492 listener_->onUiIntensiveBugreportDumpsFinished();
Paul Changc490e662020-04-11 18:14:09 +08003493 }
3494}
3495
Jichao Lie89d9c12019-11-21 19:02:51 -08003496void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) {
Gavin Corkerya44686c2022-11-23 18:16:51 +00003497 if (multiuser_get_app_id(calling_uid) == AID_SHELL ||
3498 !CalledByApi() || options_->is_consent_deferred) {
3499 // No need to get consent for shell triggered dumpstates, or not
3500 // through bugreporting API (i.e. no fd to copy back), or when consent
3501 // is deferred.
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003502 return;
3503 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003504 consent_callback_ = new ConsentCallback();
3505 const String16 incidentcompanion("incidentcompanion");
3506 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
Jichao Lie89d9c12019-11-21 19:02:51 -08003507 android::String16 package(calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003508 if (ics != nullptr) {
3509 MYLOGD("Checking user consent via incidentcompanion service\n");
Steven Leeb573eb82022-11-29 22:31:35 +08003510 int flags = 0x1; // IncidentManager.FLAG_CONFIRMATION_DIALOG
3511 if (IsConsentlessBugreportAllowed(*options_)) {
3512 flags |= 0x2; // IncidentManager.FLAG_ALLOW_CONSENTLESS_BUGREPORT
3513 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003514 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
Steven Leeb573eb82022-11-29 22:31:35 +08003515 calling_uid, package, String16(), String16(), flags, consent_callback_.get());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003516 } else {
3517 MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
3518 }
3519}
3520
Nandana Dutt5c390032019-03-12 10:52:56 +00003521bool Dumpstate::IsUserConsentDenied() const {
3522 return ds.consent_callback_ != nullptr &&
3523 ds.consent_callback_->getResult() == UserConsentResult::DENIED;
3524}
3525
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01003526bool Dumpstate::CalledByApi() const {
3527 return ds.options_->bugreport_fd.get() != -1 ? true : false;
3528}
3529
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003530void Dumpstate::CleanupTmpFiles() {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003531 android::os::UnlinkAndLogOnError(tmp_path_);
3532 android::os::UnlinkAndLogOnError(screenshot_path_);
3533 android::os::UnlinkAndLogOnError(path_);
Gavin Corkery789d7a52021-02-24 23:52:35 +00003534 if (dump_traces_path != nullptr) {
3535 android::os::UnlinkAndLogOnError(dump_traces_path);
3536 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003537}
3538
Rhed Jao5377d792020-07-16 17:37:39 +08003539void Dumpstate::EnableParallelRunIfNeeded() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003540 if (!PropertiesHelper::IsParallelRun()) {
Rhed Jao5377d792020-07-16 17:37:39 +08003541 return;
3542 }
3543 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003544 zip_entry_tasks_ = std::make_unique<TaskQueue>();
Rhed Jao5377d792020-07-16 17:37:39 +08003545}
3546
3547void Dumpstate::ShutdownDumpPool() {
3548 if (dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08003549 dump_pool_.reset();
Rhed Jao5377d792020-07-16 17:37:39 +08003550 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003551 if (zip_entry_tasks_) {
3552 zip_entry_tasks_->run(/* do_cancel = */true);
3553 zip_entry_tasks_ = nullptr;
3554 }
3555}
3556
3557void Dumpstate::EnqueueAddZipEntryAndCleanupIfNeeded(const std::string& entry_name,
3558 const std::string& entry_path) {
3559 auto func_add_zip_entry_and_cleanup = [=](bool task_cancelled) {
3560 if (!task_cancelled) {
3561 AddZipEntry(entry_name, entry_path);
3562 }
3563 android::os::UnlinkAndLogOnError(entry_path);
3564 };
3565 if (zip_entry_tasks_) {
3566 // Enqueues AddZipEntryAndCleanup function if the parallel run is enabled.
3567 zip_entry_tasks_->add(func_add_zip_entry_and_cleanup, _1);
3568 } else {
3569 // Invokes AddZipEntryAndCleanup immediately
3570 std::invoke(func_add_zip_entry_and_cleanup, /* task_cancelled = */false);
3571 }
Rhed Jao5377d792020-07-16 17:37:39 +08003572}
3573
Nandana Duttd2f5f082019-01-18 17:13:52 +00003574Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
3575 MYLOGD("User denied consent; deleting files and returning\n");
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003576 CleanupTmpFiles();
Nandana Duttd2f5f082019-01-18 17:13:52 +00003577 return USER_CONSENT_DENIED;
3578}
3579
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003580Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented(int32_t calling_uid) {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003581 // If the caller has asked to copy the bugreport over to their directory, we need explicit
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003582 // user consent (unless the caller is Shell).
3583 UserConsentResult consent_result;
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003584 if (multiuser_get_app_id(calling_uid) == AID_SHELL) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003585 consent_result = UserConsentResult::APPROVED;
3586 } else {
3587 consent_result = consent_callback_->getResult();
3588 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003589 if (consent_result == UserConsentResult::UNAVAILABLE) {
3590 // User has not responded yet.
3591 uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
Hunter Knepshield70610fa2020-01-03 15:27:33 -08003592 // Telephony is a fast report type, particularly on user builds where information may be
3593 // more aggressively limited. To give the user time to read the consent dialog, increase the
3594 // timeout.
3595 uint64_t timeout_ms = options_->telephony_only ? TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS
3596 : USER_CONSENT_TIMEOUT_MS;
3597 if (elapsed_ms < timeout_ms) {
3598 uint delay_seconds = (timeout_ms - elapsed_ms) / 1000;
Nandana Duttd2f5f082019-01-18 17:13:52 +00003599 MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
3600 sleep(delay_seconds);
3601 }
3602 consent_result = consent_callback_->getResult();
3603 }
3604 if (consent_result == UserConsentResult::DENIED) {
3605 // User has explicitly denied sharing with the app. To be safe delete the
3606 // internal bugreport & tmp files.
3607 return HandleUserConsentDenied();
3608 }
3609 if (consent_result == UserConsentResult::APPROVED) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00003610 bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
3611 if (copy_succeeded) {
3612 android::os::UnlinkAndLogOnError(path_);
Abhijeet Kaur9ce94672020-04-01 17:22:36 +01003613 if (options_->do_screenshot &&
3614 options_->screenshot_fd.get() != -1 &&
3615 !options_->is_screenshot_copied) {
3616 copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
3617 options_->screenshot_fd.get());
3618 options_->is_screenshot_copied = copy_succeeded;
3619 if (copy_succeeded) {
3620 android::os::UnlinkAndLogOnError(screenshot_path_);
3621 }
3622 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003623 }
3624 return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
3625 } else if (consent_result == UserConsentResult::UNAVAILABLE) {
3626 // consent_result is still UNAVAILABLE. The user has likely not responded yet.
3627 // Since we do not have user consent to share the bugreport it does not get
3628 // copied over to the calling app but remains in the internal directory from
3629 // where the user can manually pull it.
Paul Changce644212021-05-11 16:06:45 +08003630 std::string final_path = GetPath(".zip");
3631 bool copy_succeeded = android::os::CopyFileToFile(path_, final_path);
3632 if (copy_succeeded) {
3633 android::os::UnlinkAndLogOnError(path_);
3634 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003635 return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
3636 }
3637 // Unknown result; must be a programming error.
3638 MYLOGE("Unknown user consent result:%d\n", consent_result);
3639 return Dumpstate::RunStatus::ERROR;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003640}
3641
Nandana Duttf02564e2019-02-15 15:24:24 +00003642Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003643 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
3644 Dumpstate::RunStatus status = options->Initialize(argc, argv);
3645 if (status == Dumpstate::RunStatus::OK) {
Nandana Duttf02564e2019-02-15 15:24:24 +00003646 SetOptions(std::move(options));
Nandana Duttd2f5f082019-01-18 17:13:52 +00003647 // When directly running dumpstate binary, the output is not expected to be written
3648 // to any external file descriptor.
Nandana Duttf02564e2019-02-15 15:24:24 +00003649 assert(options_->bugreport_fd.get() == -1);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003650
3651 // calling_uid and calling_package are for user consent to share the bugreport with
Abhijeet Kaura407fb82020-03-27 12:51:12 +00003652 // an app; they are irrelevant here because bugreport is triggered via command line.
3653 // Update Last ID before calling Run().
3654 Initialize();
Nikhil Kumarb70622a2023-06-15 15:37:19 +01003655 status = Run(0 /* calling_uid */, "" /* calling_package */);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003656 }
Nandana Duttf02564e2019-02-15 15:24:24 +00003657 return status;
3658}
3659
3660/* Main entry point for dumpstate binary. */
3661int run_main(int argc, char* argv[]) {
3662 Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003663
3664 switch (status) {
3665 case Dumpstate::RunStatus::OK:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003666 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003667 case Dumpstate::RunStatus::HELP:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003668 ShowUsage();
3669 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003670 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003671 fprintf(stderr, "Invalid combination of args\n");
3672 ShowUsage();
3673 exit(1);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003674 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003675 FALLTHROUGH_INTENDED;
3676 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3677 FALLTHROUGH_INTENDED;
3678 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003679 exit(2);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003680 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003681}
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003682
3683// TODO(111441001): Default DumpOptions to sensible values.
3684Dumpstate::Dumpstate(const std::string& version)
3685 : pid_(getpid()),
3686 options_(new Dumpstate::DumpOptions()),
Nandana Dutt402a8392019-06-14 14:25:13 +01003687 last_reported_percent_progress_(0),
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003688 version_(version),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003689 now_(time(nullptr)),
3690 open_socket_fn_(open_socket) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003691}
3692
3693Dumpstate& Dumpstate::GetInstance() {
3694 static Dumpstate singleton_(android::base::GetProperty("dumpstate.version", VERSION_CURRENT));
3695 return singleton_;
3696}
3697
Rhed Jao5377d792020-07-16 17:37:39 +08003698DurationReporter::DurationReporter(const std::string& title, bool logcat_only, bool verbose,
3699 int duration_fd) : title_(title), logcat_only_(logcat_only), verbose_(verbose),
3700 duration_fd_(duration_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003701 if (!title_.empty()) {
3702 started_ = Nanotime();
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003703 if (title_.find("SHOW MAP") == std::string::npos) {
3704 ATRACE_ASYNC_BEGIN(title_.c_str(), 0);
3705 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003706 }
3707}
3708
3709DurationReporter::~DurationReporter() {
3710 if (!title_.empty()) {
3711 float elapsed = (float)(Nanotime() - started_) / NANOS_PER_SEC;
chenqiwuaf8b2d92019-12-12 18:53:51 +08003712 if (elapsed >= .5f || verbose_) {
3713 MYLOGD("Duration of '%s': %.2fs\n", title_.c_str(), elapsed);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003714 }
chenqiwuaf8b2d92019-12-12 18:53:51 +08003715 if (!logcat_only_) {
3716 // Use "Yoda grammar" to make it easier to grep|sort sections.
Rhed Jao5377d792020-07-16 17:37:39 +08003717 dprintf(duration_fd_, "------ %.3fs was the duration of '%s' ------\n",
3718 elapsed, title_.c_str());
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003719 }
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003720 if (title_.find("SHOW MAP") == std::string::npos) {
3721 ATRACE_ASYNC_END(title_.c_str(), 0);
3722 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003723 }
3724}
3725
3726const int32_t Progress::kDefaultMax = 5000;
3727
3728Progress::Progress(const std::string& path) : Progress(Progress::kDefaultMax, 1.1, path) {
3729}
3730
3731Progress::Progress(int32_t initial_max, int32_t progress, float growth_factor)
3732 : Progress(initial_max, growth_factor, "") {
3733 progress_ = progress;
3734}
3735
3736Progress::Progress(int32_t initial_max, float growth_factor, const std::string& path)
3737 : initial_max_(initial_max),
3738 progress_(0),
3739 max_(initial_max),
3740 growth_factor_(growth_factor),
3741 n_runs_(0),
3742 average_max_(0),
3743 path_(path) {
3744 if (!path_.empty()) {
3745 Load();
3746 }
3747}
3748
3749void Progress::Load() {
3750 MYLOGD("Loading stats from %s\n", path_.c_str());
3751 std::string content;
3752 if (!android::base::ReadFileToString(path_, &content)) {
3753 MYLOGI("Could not read stats from %s; using max of %d\n", path_.c_str(), max_);
3754 return;
3755 }
3756 if (content.empty()) {
3757 MYLOGE("No stats (empty file) on %s; using max of %d\n", path_.c_str(), max_);
3758 return;
3759 }
3760 std::vector<std::string> lines = android::base::Split(content, "\n");
3761
3762 if (lines.size() < 1) {
3763 MYLOGE("Invalid stats on file %s: not enough lines (%d). Using max of %d\n", path_.c_str(),
3764 (int)lines.size(), max_);
3765 return;
3766 }
3767 char* ptr;
3768 n_runs_ = strtol(lines[0].c_str(), &ptr, 10);
3769 average_max_ = strtol(ptr, nullptr, 10);
3770 if (n_runs_ <= 0 || average_max_ <= 0 || n_runs_ > STATS_MAX_N_RUNS ||
3771 average_max_ > STATS_MAX_AVERAGE) {
3772 MYLOGE("Invalid stats line on file %s: %s\n", path_.c_str(), lines[0].c_str());
3773 initial_max_ = Progress::kDefaultMax;
3774 } else {
3775 initial_max_ = average_max_;
3776 }
3777 max_ = initial_max_;
3778
3779 MYLOGI("Average max progress: %d in %d runs; estimated max: %d\n", average_max_, n_runs_, max_);
3780}
3781
3782void Progress::Save() {
3783 int32_t total = n_runs_ * average_max_ + progress_;
3784 int32_t runs = n_runs_ + 1;
3785 int32_t average = floor(((float)total) / runs);
3786 MYLOGI("Saving stats (total=%d, runs=%d, average=%d) on %s\n", total, runs, average,
3787 path_.c_str());
3788 if (path_.empty()) {
3789 return;
3790 }
3791
3792 std::string content = android::base::StringPrintf("%d %d\n", runs, average);
3793 if (!android::base::WriteStringToFile(content, path_)) {
3794 MYLOGE("Could not save stats on %s\n", path_.c_str());
3795 }
3796}
3797
3798int32_t Progress::Get() const {
3799 return progress_;
3800}
3801
3802bool Progress::Inc(int32_t delta_sec) {
3803 bool changed = false;
3804 if (delta_sec >= 0) {
3805 progress_ += delta_sec;
3806 if (progress_ > max_) {
3807 int32_t old_max = max_;
3808 max_ = floor((float)progress_ * growth_factor_);
3809 MYLOGD("Adjusting max progress from %d to %d\n", old_max, max_);
3810 changed = true;
3811 }
3812 }
3813 return changed;
3814}
3815
3816int32_t Progress::GetMax() const {
3817 return max_;
3818}
3819
3820int32_t Progress::GetInitialMax() const {
3821 return initial_max_;
3822}
3823
3824void Progress::Dump(int fd, const std::string& prefix) const {
3825 const char* pr = prefix.c_str();
3826 dprintf(fd, "%sprogress: %d\n", pr, progress_);
3827 dprintf(fd, "%smax: %d\n", pr, max_);
3828 dprintf(fd, "%sinitial_max: %d\n", pr, initial_max_);
3829 dprintf(fd, "%sgrowth_factor: %0.2f\n", pr, growth_factor_);
3830 dprintf(fd, "%spath: %s\n", pr, path_.c_str());
3831 dprintf(fd, "%sn_runs: %d\n", pr, n_runs_);
3832 dprintf(fd, "%saverage_max: %d\n", pr, average_max_);
3833}
3834
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003835std::string Dumpstate::GetPath(const std::string& suffix) const {
3836 return GetPath(bugreport_internal_dir_, suffix);
3837}
3838
3839std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
3840 return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
3841 name_.c_str(), suffix.c_str());
3842}
3843
3844void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
3845 progress_ = std::move(progress);
3846}
3847
3848void for_each_userid(void (*func)(int), const char *header) {
3849 std::string title = header == nullptr ? "for_each_userid" : android::base::StringPrintf(
3850 "for_each_userid(%s)", header);
3851 DurationReporter duration_reporter(title);
3852 if (PropertiesHelper::IsDryRun()) return;
3853
3854 DIR *d;
3855 struct dirent *de;
3856
3857 if (header) printf("\n------ %s ------\n", header);
3858 func(0);
3859
3860 if (!(d = opendir("/data/system/users"))) {
3861 printf("Failed to open /data/system/users (%s)\n", strerror(errno));
3862 return;
3863 }
3864
3865 while ((de = readdir(d))) {
3866 int userid;
3867 if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
3868 continue;
3869 }
3870 func(userid);
3871 }
3872
3873 closedir(d);
3874}
3875
3876static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
3877 DIR *d;
3878 struct dirent *de;
3879
3880 if (!(d = opendir("/proc"))) {
3881 printf("Failed to open /proc (%s)\n", strerror(errno));
3882 return;
3883 }
3884
3885 if (header) printf("\n------ %s ------\n", header);
3886 while ((de = readdir(d))) {
3887 if (ds.IsUserConsentDenied()) {
3888 MYLOGE(
3889 "Returning early because user denied consent to share bugreport with calling app.");
3890 closedir(d);
3891 return;
3892 }
3893 int pid;
3894 int fd;
3895 char cmdpath[255];
3896 char cmdline[255];
3897
3898 if (!(pid = atoi(de->d_name))) {
3899 continue;
3900 }
3901
3902 memset(cmdline, 0, sizeof(cmdline));
3903
3904 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
3905 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3906 TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
3907 close(fd);
3908 if (cmdline[0]) {
3909 helper(pid, cmdline, arg);
3910 continue;
3911 }
3912 }
3913
3914 // if no cmdline, a kernel thread has comm
3915 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
3916 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3917 TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
3918 close(fd);
3919 if (cmdline[1]) {
3920 cmdline[0] = '[';
3921 size_t len = strcspn(cmdline, "\f\b\r\n");
3922 cmdline[len] = ']';
3923 cmdline[len+1] = '\0';
3924 }
3925 }
3926 if (!cmdline[0]) {
3927 strcpy(cmdline, "N/A");
3928 }
3929 helper(pid, cmdline, arg);
3930 }
3931
3932 closedir(d);
3933}
3934
3935static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
3936 for_each_pid_func *func = (for_each_pid_func*) arg;
3937 func(pid, cmdline);
3938}
3939
3940void for_each_pid(for_each_pid_func func, const char *header) {
3941 std::string title = header == nullptr ? "for_each_pid"
3942 : android::base::StringPrintf("for_each_pid(%s)", header);
3943 DurationReporter duration_reporter(title);
3944 if (PropertiesHelper::IsDryRun()) return;
3945
3946 __for_each_pid(for_each_pid_helper, header, (void *) func);
3947}
3948
3949static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
3950 DIR *d;
3951 struct dirent *de;
3952 char taskpath[255];
3953 for_each_tid_func *func = (for_each_tid_func *) arg;
3954
3955 snprintf(taskpath, sizeof(taskpath), "/proc/%d/task", pid);
3956
3957 if (!(d = opendir(taskpath))) {
3958 printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
3959 return;
3960 }
3961
3962 func(pid, pid, cmdline);
3963
3964 while ((de = readdir(d))) {
3965 if (ds.IsUserConsentDenied()) {
3966 MYLOGE(
3967 "Returning early because user denied consent to share bugreport with calling app.");
3968 closedir(d);
3969 return;
3970 }
3971 int tid;
3972 int fd;
3973 char commpath[255];
3974 char comm[255];
3975
3976 if (!(tid = atoi(de->d_name))) {
3977 continue;
3978 }
3979
3980 if (tid == pid)
3981 continue;
3982
3983 snprintf(commpath, sizeof(commpath), "/proc/%d/comm", tid);
3984 memset(comm, 0, sizeof(comm));
3985 if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
3986 strcpy(comm, "N/A");
3987 } else {
3988 char *c;
3989 TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
3990 close(fd);
3991
3992 c = strrchr(comm, '\n');
3993 if (c) {
3994 *c = '\0';
3995 }
3996 }
3997 func(pid, tid, comm);
3998 }
3999
4000 closedir(d);
4001}
4002
4003void for_each_tid(for_each_tid_func func, const char *header) {
4004 std::string title = header == nullptr ? "for_each_tid"
4005 : android::base::StringPrintf("for_each_tid(%s)", header);
4006 DurationReporter duration_reporter(title);
4007
4008 if (PropertiesHelper::IsDryRun()) return;
4009
4010 __for_each_pid(for_each_tid_helper, header, (void *) func);
4011}
4012
4013void show_wchan(int pid, int tid, const char *name) {
4014 if (PropertiesHelper::IsDryRun()) return;
4015
4016 char path[255];
4017 char buffer[255];
4018 int fd, ret, save_errno;
4019 char name_buffer[255];
4020
4021 memset(buffer, 0, sizeof(buffer));
4022
4023 snprintf(path, sizeof(path), "/proc/%d/wchan", tid);
4024 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
4025 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
4026 return;
4027 }
4028
4029 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
4030 save_errno = errno;
4031 close(fd);
4032
4033 if (ret < 0) {
4034 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
4035 return;
4036 }
4037
4038 snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
4039 pid == tid ? 0 : 3, "", name);
4040
4041 printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
4042
4043 return;
4044}
4045
4046// print time in centiseconds
4047static void snprcent(char *buffer, size_t len, size_t spc,
4048 unsigned long long time) {
4049 static long hz; // cache discovered hz
4050
4051 if (hz <= 0) {
4052 hz = sysconf(_SC_CLK_TCK);
4053 if (hz <= 0) {
4054 hz = 1000;
4055 }
4056 }
4057
4058 // convert to centiseconds
4059 time = (time * 100 + (hz / 2)) / hz;
4060
4061 char str[16];
4062
4063 snprintf(str, sizeof(str), " %llu.%02u",
4064 time / 100, (unsigned)(time % 100));
4065 size_t offset = strlen(buffer);
4066 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
4067 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
4068}
4069
4070// print permille as a percent
4071static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
4072 char str[16];
4073
4074 snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
4075 size_t offset = strlen(buffer);
4076 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
4077 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
4078}
4079
4080void show_showtime(int pid, const char *name) {
4081 if (PropertiesHelper::IsDryRun()) return;
4082
4083 char path[255];
4084 char buffer[1023];
4085 int fd, ret, save_errno;
4086
4087 memset(buffer, 0, sizeof(buffer));
4088
4089 snprintf(path, sizeof(path), "/proc/%d/stat", pid);
4090 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
4091 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
4092 return;
4093 }
4094
4095 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
4096 save_errno = errno;
4097 close(fd);
4098
4099 if (ret < 0) {
4100 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
4101 return;
4102 }
4103
4104 // field 14 is utime
4105 // field 15 is stime
4106 // field 42 is iotime
4107 unsigned long long utime = 0, stime = 0, iotime = 0;
4108 if (sscanf(buffer,
4109 "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
4110 "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
4111 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
4112 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
4113 &utime, &stime, &iotime) != 3) {
4114 return;
4115 }
4116
4117 unsigned long long total = utime + stime;
4118 if (!total) {
4119 return;
4120 }
4121
4122 unsigned permille = (iotime * 1000 + (total / 2)) / total;
4123 if (permille > 1000) {
4124 permille = 1000;
4125 }
4126
4127 // try to beautify and stabilize columns at <80 characters
4128 snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
4129 if ((name[0] != '[') || utime) {
4130 snprcent(buffer, sizeof(buffer), 57, utime);
4131 }
4132 snprcent(buffer, sizeof(buffer), 65, stime);
4133 if ((name[0] != '[') || iotime) {
4134 snprcent(buffer, sizeof(buffer), 73, iotime);
4135 }
4136 if (iotime) {
4137 snprdec(buffer, sizeof(buffer), 79, permille);
4138 }
4139 puts(buffer); // adds a trailing newline
4140
4141 return;
4142}
4143
4144void do_dmesg() {
4145 const char *title = "KERNEL LOG (dmesg)";
4146 DurationReporter duration_reporter(title);
4147 printf("------ %s ------\n", title);
4148
4149 if (PropertiesHelper::IsDryRun()) return;
4150
4151 /* Get size of kernel buffer */
4152 int size = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
4153 if (size <= 0) {
4154 printf("Unexpected klogctl return value: %d\n\n", size);
4155 return;
4156 }
4157 char *buf = (char *) malloc(size + 1);
4158 if (buf == nullptr) {
4159 printf("memory allocation failed\n\n");
4160 return;
4161 }
4162 int retval = klogctl(KLOG_READ_ALL, buf, size);
4163 if (retval < 0) {
4164 printf("klogctl failure\n\n");
4165 free(buf);
4166 return;
4167 }
4168 buf[retval] = '\0';
4169 printf("%s\n\n", buf);
4170 free(buf);
4171 return;
4172}
4173
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004174int Dumpstate::DumpFile(const std::string& title, const std::string& path) {
4175 DurationReporter duration_reporter(title);
4176
4177 int status = DumpFileToFd(STDOUT_FILENO, title, path);
4178
4179 UpdateProgress(WEIGHT_FILE);
4180
4181 return status;
4182}
4183
4184int read_file_as_long(const char *path, long int *output) {
4185 int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
4186 if (fd < 0) {
4187 int err = errno;
4188 MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
4189 return -1;
4190 }
4191 char buffer[50];
4192 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
4193 if (bytes_read == -1) {
4194 MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
4195 return -2;
4196 }
4197 if (bytes_read == 0) {
4198 MYLOGE("File %s is empty\n", path);
4199 return -3;
4200 }
4201 *output = atoi(buffer);
4202 return 0;
4203}
4204
4205/* calls skip to gate calling dump_from_fd recursively
4206 * in the specified directory. dump_from_fd defaults to
4207 * dump_file_from_fd above when set to NULL. skip defaults
4208 * to false when set to NULL. dump_from_fd will always be
4209 * called with title NULL.
4210 */
4211int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
4212 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4213 DurationReporter duration_reporter(title);
4214 DIR *dirp;
4215 struct dirent *d;
4216 char *newpath = nullptr;
4217 const char *slash = "/";
4218 int retval = 0;
4219
4220 if (!title.empty()) {
4221 printf("------ %s (%s) ------\n", title.c_str(), dir);
4222 }
4223 if (PropertiesHelper::IsDryRun()) return 0;
4224
4225 if (dir[strlen(dir) - 1] == '/') {
4226 ++slash;
4227 }
4228 dirp = opendir(dir);
4229 if (dirp == nullptr) {
4230 retval = -errno;
4231 MYLOGE("%s: %s\n", dir, strerror(errno));
4232 return retval;
4233 }
4234
4235 if (!dump_from_fd) {
4236 dump_from_fd = dump_file_from_fd;
4237 }
4238 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4239 if ((d->d_name[0] == '.')
4240 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4241 || (d->d_name[1] == '\0'))) {
4242 continue;
4243 }
4244 asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
4245 (d->d_type == DT_DIR) ? "/" : "");
4246 if (!newpath) {
4247 retval = -errno;
4248 continue;
4249 }
4250 if (skip && (*skip)(newpath)) {
4251 continue;
4252 }
4253 if (d->d_type == DT_DIR) {
4254 int ret = dump_files("", newpath, skip, dump_from_fd);
4255 if (ret < 0) {
4256 retval = ret;
4257 }
4258 continue;
4259 }
4260 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
4261 if (fd.get() < 0) {
4262 retval = -1;
4263 printf("*** %s: %s\n", newpath, strerror(errno));
4264 continue;
4265 }
4266 (*dump_from_fd)(nullptr, newpath, fd.get());
4267 }
4268 closedir(dirp);
4269 if (!title.empty()) {
4270 printf("\n");
4271 }
4272 return retval;
4273}
4274
4275/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
4276 * it's possible to avoid issues where opening the file itself can get
4277 * stuck.
4278 */
4279int dump_file_from_fd(const char *title, const char *path, int fd) {
4280 if (PropertiesHelper::IsDryRun()) return 0;
4281
4282 int flags = fcntl(fd, F_GETFL);
4283 if (flags == -1) {
4284 printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
4285 return -1;
4286 } else if (!(flags & O_NONBLOCK)) {
4287 printf("*** %s: fd must have O_NONBLOCK set.\n", path);
4288 return -1;
4289 }
4290 return DumpFileFromFdToFd(title, path, fd, STDOUT_FILENO, PropertiesHelper::IsDryRun());
4291}
4292
4293int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004294 const CommandOptions& options, bool verbose_duration, int out_fd) {
4295 DurationReporter duration_reporter(title, false /* logcat_only */,
4296 verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004297
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004298 int status = RunCommandToFd(out_fd, title, full_command, options);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004299
4300 /* TODO: for now we're simplifying the progress calculation by using the
4301 * timeout as the weight. It's a good approximation for most cases, except when calling dumpsys,
4302 * where its weight should be much higher proportionally to its timeout.
4303 * Ideally, it should use a options.EstimatedDuration() instead...*/
4304 UpdateProgress(options.Timeout());
4305
4306 return status;
4307}
4308
4309void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
Rhed Jaoe017f982020-07-21 17:58:41 +08004310 const CommandOptions& options, long dumpsysTimeoutMs, int out_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004311 long timeout_ms = dumpsysTimeoutMs > 0 ? dumpsysTimeoutMs : options.TimeoutInMs();
4312 std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-T", std::to_string(timeout_ms)};
4313 dumpsys.insert(dumpsys.end(), dumpsys_args.begin(), dumpsys_args.end());
Rhed Jaoe017f982020-07-21 17:58:41 +08004314 RunCommand(title, dumpsys, options, false, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004315}
4316
Dieter Hsu105ad0c2020-09-29 15:23:33 +08004317static int open_socket(const char* service) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004318 int s = android_get_control_socket(service);
4319 if (s < 0) {
4320 MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
4321 return -1;
4322 }
4323 fcntl(s, F_SETFD, FD_CLOEXEC);
4324
4325 // Set backlog to 0 to make sure that queue size will be minimum.
4326 // In Linux, because the minimum queue will be 1, connect() will be blocked
4327 // if the other clients already called connect() and the connection request was not accepted.
4328 if (listen(s, 0) < 0) {
4329 MYLOGE("listen(control socket): %s\n", strerror(errno));
4330 return -1;
4331 }
4332
4333 struct sockaddr addr;
4334 socklen_t alen = sizeof(addr);
Abhijeet Kaur2113cae2019-09-13 09:24:15 +01004335 int fd = accept4(s, &addr, &alen, SOCK_CLOEXEC);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004336
4337 // Close socket just after accept(), to make sure that connect() by client will get error
4338 // when the socket is used by the other services.
4339 // There is still a race condition possibility between accept and close, but there is no way
4340 // to close-on-accept atomically.
4341 // See detail; b/123306389#comment25
4342 close(s);
4343
4344 if (fd < 0) {
4345 MYLOGE("accept(control socket): %s\n", strerror(errno));
4346 return -1;
4347 }
4348
4349 return fd;
4350}
4351
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004352// TODO: should call is_valid_output_file and/or be merged into it.
4353void create_parent_dirs(const char *path) {
4354 char *chp = const_cast<char *> (path);
4355
4356 /* skip initial slash */
4357 if (chp[0] == '/')
4358 chp++;
4359
4360 /* create leading directories, if necessary */
4361 struct stat dir_stat;
4362 while (chp && chp[0]) {
4363 chp = strchr(chp, '/');
4364 if (chp) {
4365 *chp = 0;
4366 if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
4367 MYLOGI("Creating directory %s\n", path);
4368 if (mkdir(path, 0770)) { /* drwxrwx--- */
4369 MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
4370 } else if (chown(path, AID_SHELL, AID_SHELL)) {
4371 MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
4372 }
4373 }
4374 *chp++ = '/';
4375 }
4376 }
4377}
4378
4379bool _redirect_to_file(FILE* redirect, char* path, int truncate_flag) {
4380 create_parent_dirs(path);
4381
4382 int fd = TEMP_FAILURE_RETRY(open(path,
4383 O_WRONLY | O_CREAT | truncate_flag | O_CLOEXEC | O_NOFOLLOW,
4384 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
4385 if (fd < 0) {
4386 MYLOGE("%s: %s\n", path, strerror(errno));
4387 return false;
4388 }
4389
4390 TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
4391 close(fd);
4392 return true;
4393}
4394
4395bool redirect_to_file(FILE* redirect, char* path) {
4396 return _redirect_to_file(redirect, path, O_TRUNC);
4397}
4398
4399bool redirect_to_existing_file(FILE* redirect, char* path) {
4400 return _redirect_to_file(redirect, path, O_APPEND);
4401}
4402
4403void dump_route_tables() {
4404 DurationReporter duration_reporter("DUMP ROUTE TABLES");
4405 if (PropertiesHelper::IsDryRun()) return;
4406 const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
4407 ds.DumpFile("RT_TABLES", RT_TABLES_PATH);
4408 FILE* fp = fopen(RT_TABLES_PATH, "re");
4409 if (!fp) {
4410 printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
4411 return;
4412 }
4413 char table[16];
4414 // Each line has an integer (the table number), a space, and a string (the table name). We only
4415 // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
4416 // Add a fixed max limit so this doesn't go awry.
4417 for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
4418 RunCommand("ROUTE TABLE IPv4", {"ip", "-4", "route", "show", "table", table});
4419 RunCommand("ROUTE TABLE IPv6", {"ip", "-6", "route", "show", "table", table});
4420 }
4421 fclose(fp);
4422}
4423
Li Li830179f2022-01-04 12:53:29 -08004424void dump_frozen_cgroupfs(const char *dir, int level,
4425 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4426 DIR *dirp;
4427 struct dirent *d;
4428 char *newpath = nullptr;
4429
4430 dirp = opendir(dir);
4431 if (dirp == nullptr) {
4432 MYLOGE("%s: %s\n", dir, strerror(errno));
4433 return;
4434 }
4435
4436 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4437 if ((d->d_name[0] == '.')
4438 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4439 || (d->d_name[1] == '\0'))) {
4440 continue;
4441 }
4442 if (d->d_type == DT_DIR) {
4443 asprintf(&newpath, "%s/%s/", dir, d->d_name);
4444 if (!newpath) {
4445 continue;
4446 }
4447 if (level == 0 && !strncmp(d->d_name, "uid_", 4)) {
4448 dump_frozen_cgroupfs(newpath, 1, dump_from_fd);
4449 } else if (level == 1 && !strncmp(d->d_name, "pid_", 4)) {
4450 char *freezer = nullptr;
4451 asprintf(&freezer, "%s/%s", newpath, "cgroup.freeze");
4452 if (freezer) {
4453 FILE* fp = fopen(freezer, "r");
4454 if (fp != NULL) {
4455 int frozen;
4456 fscanf(fp, "%d", &frozen);
4457 if (frozen > 0) {
4458 dump_files("", newpath, skip_none, dump_from_fd);
4459 }
4460 fclose(fp);
4461 }
4462 free(freezer);
4463 }
4464 }
4465 }
4466 }
4467 closedir(dirp);
4468}
4469
4470void dump_frozen_cgroupfs() {
Li Li830179f2022-01-04 12:53:29 -08004471 MYLOGD("Adding frozen processes from %s\n", CGROUPFS_DIR);
4472 DurationReporter duration_reporter("FROZEN CGROUPFS");
4473 if (PropertiesHelper::IsDryRun()) return;
4474 dump_frozen_cgroupfs(CGROUPFS_DIR, 0, _add_file_from_fd);
4475}
4476
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004477void Dumpstate::UpdateProgress(int32_t delta_sec) {
4478 if (progress_ == nullptr) {
4479 MYLOGE("UpdateProgress: progress_ not set\n");
4480 return;
4481 }
Rhed Jaobf63d8a2020-07-21 15:42:55 +08004482 // This function updates progress related members of the dumpstate and reports
4483 // progress percentage to the bugreport client. Since it could be called by
4484 // different dump tasks at the same time if the parallel run is enabled, a
4485 // mutex lock is necessary here to synchronize the call.
4486 std::lock_guard<std::recursive_mutex> lock(mutex_);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004487
4488 // Always update progess so stats can be tuned...
Nandana Dutt402a8392019-06-14 14:25:13 +01004489 progress_->Inc(delta_sec);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004490
4491 // ...but only notifiy listeners when necessary.
4492 if (!options_->do_progress_updates) return;
4493
4494 int progress = progress_->Get();
4495 int max = progress_->GetMax();
Nandana Dutt402a8392019-06-14 14:25:13 +01004496 int percent = 100 * progress / max;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004497
Nandana Dutt402a8392019-06-14 14:25:13 +01004498 if (last_reported_percent_progress_ > 0 && percent <= last_reported_percent_progress_) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004499 return;
4500 }
Nandana Dutt402a8392019-06-14 14:25:13 +01004501 last_reported_percent_progress_ = percent;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004502
4503 if (control_socket_fd_ >= 0) {
4504 dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
4505 fsync(control_socket_fd_);
4506 }
4507
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004508 if (listener_ != nullptr) {
Nandana Dutt235c6672019-11-14 15:22:32 +00004509 if (percent % 10 == 0) {
4510 // We don't want to spam logcat, so only log multiples of 10.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004511 MYLOGD("Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004512 } else {
4513 // stderr is ignored on normal invocations, but useful when calling
4514 // /system/bin/dumpstate directly for debuggging.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004515 fprintf(stderr, "Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004516 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004517
4518 listener_->onProgress(percent);
4519 }
4520}
4521
4522void Dumpstate::TakeScreenshot(const std::string& path) {
4523 const std::string& real_path = path.empty() ? screenshot_path_ : path;
4524 int status =
4525 RunCommand("", {"/system/bin/screencap", "-p", real_path},
4526 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
4527 if (status == 0) {
4528 MYLOGD("Screenshot saved on %s\n", real_path.c_str());
4529 } else {
4530 MYLOGE("Failed to take screenshot on %s\n", real_path.c_str());
4531 }
Paul Chang0d2aad72020-02-13 20:04:03 +08004532 if (listener_ != nullptr) {
4533 // Show a visual indication to indicate screenshot is taken via
4534 // IDumpstateListener.onScreenshotTaken()
4535 listener_->onScreenshotTaken(status == 0);
4536 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004537}
4538
4539bool is_dir(const char* pathname) {
4540 struct stat info;
4541 if (stat(pathname, &info) == -1) {
4542 return false;
4543 }
4544 return S_ISDIR(info.st_mode);
4545}
4546
4547time_t get_mtime(int fd, time_t default_mtime) {
4548 struct stat info;
4549 if (fstat(fd, &info) == -1) {
4550 return default_mtime;
4551 }
4552 return info.st_mtime;
4553}