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