blob: 4f80190954e1b532d1e34ba26d29969466192ee4 [file] [log] [blame]
Colin Crossf45fa6b2012-03-26 12:38:26 -07001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Felipe Lemef0292972016-11-22 13:57:05 -080016
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070017#define LOG_TAG "dumpstate"
Kevin Jeon2c02e8e2022-07-07 21:45:17 +000018#define ATRACE_TAG ATRACE_TAG_ALWAYS
Colin Crossf45fa6b2012-03-26 12:38:26 -070019
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -070020#include <dirent.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070021#include <errno.h>
22#include <fcntl.h>
Nikita Ioffea325a572019-05-16 19:49:47 +010023#include <inttypes.h>
Felipe Lemead5f6c42015-11-30 14:26:46 -080024#include <libgen.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070025#include <limits.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010026#include <math.h>
27#include <poll.h>
Mark Salyzyn8f37aa52015-06-12 12:28:24 -070028#include <stdbool.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070029#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -070032#include <sys/mount.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080033#include <sys/poll.h>
Christopher Ferris7dc7f322014-07-22 16:08:19 -070034#include <sys/prctl.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070035#include <sys/resource.h>
36#include <sys/stat.h>
37#include <sys/time.h>
38#include <sys/wait.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010039#include <signal.h>
40#include <stdarg.h>
41#include <string.h>
42#include <sys/capability.h>
43#include <sys/inotify.h>
44#include <sys/klog.h>
45#include <time.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070046#include <unistd.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070047
48#include <chrono>
Hridya Valsarajuac582cd2019-08-05 15:39:54 -070049#include <cmath>
Abhijeet Kaurd3cca0d2019-03-25 12:04:16 +000050#include <fstream>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070051#include <functional>
52#include <future>
Narayan Kamath8f788292017-05-25 13:20:39 +010053#include <memory>
Hridya Valsarajuac582cd2019-08-05 15:39:54 -070054#include <numeric>
Narayan Kamath8f788292017-05-25 13:20:39 +010055#include <regex>
56#include <set>
57#include <string>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070058#include <utility>
Narayan Kamath8f788292017-05-25 13:20:39 +010059#include <vector>
Colin Crossf45fa6b2012-03-26 12:38:26 -070060
Kedar Chitnis9fd8c052021-11-16 09:09:22 +000061#include <aidl/android/hardware/dumpstate/IDumpstateDevice.h>
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +000062#include <android_app_admin_flags.h>
Felipe Leme96c2bbb2016-09-26 09:21:21 -070063#include <android-base/file.h>
64#include <android-base/properties.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070065#include <android-base/scopeguard.h>
Elliott Hughes9dc117c2015-12-07 14:21:50 -080066#include <android-base/stringprintf.h>
Naveen Kalla058e1e82016-10-19 21:38:44 -070067#include <android-base/strings.h>
Andreas Gampeaff68432016-07-18 18:01:27 -070068#include <android-base/unique_fd.h>
Kedar Chitnis9fd8c052021-11-16 09:09:22 +000069#include <android/binder_manager.h>
70#include <android/binder_process.h>
Nikita Ioffea325a572019-05-16 19:49:47 +010071#include <android/content/pm/IPackageManagerNative.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080072#include <android/hardware/dumpstate/1.0/IDumpstateDevice.h>
Hunter Knepshield8540faf2020-02-04 19:47:20 -080073#include <android/hardware/dumpstate/1.1/IDumpstateDevice.h>
74#include <android/hardware/dumpstate/1.1/types.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080075#include <android/hidl/manager/1.0/IServiceManager.h>
Nandana Duttd2f5f082019-01-18 17:13:52 +000076#include <android/os/IIncidentCompanion.h>
Nikita Ioffea325a572019-05-16 19:49:47 +010077#include <binder/IServiceManager.h>
Nikhil Kumar28ce35e2023-01-10 14:32:44 +000078#include <cutils/multiuser.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080079#include <cutils/native_handle.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070080#include <cutils/properties.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010081#include <cutils/sockets.h>
Kevin Jeon2c02e8e2022-07-07 21:45:17 +000082#include <cutils/trace.h>
Nandana Duttfaafd522019-03-11 09:23:09 +000083#include <debuggerd/client.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080084#include <dumpsys.h>
Nandana Duttfaafd522019-03-11 09:23:09 +000085#include <dumputils/dump_utils.h>
Sahana Raof35ed432019-07-12 10:47:52 +010086#include <hardware_legacy/power.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080087#include <hidl/ServiceManagement.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010088#include <log/log.h>
Tom Cherryf4472f32020-08-05 09:31:17 -070089#include <log/log_read.h>
Felipe Leme75876a22016-10-27 16:31:27 -070090#include <openssl/sha.h>
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070091#include <private/android_filesystem_config.h>
92#include <private/android_logger.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080093#include <serviceutils/PriorityDumper.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070094#include <utils/StrongPointer.h>
Devin Moore8df81bb2022-06-08 22:47:02 +000095#include <vintf/VintfObject.h>
Felipe Lemef0292972016-11-22 13:57:05 -080096#include "DumpstateInternal.h"
Felipe Leme75876a22016-10-27 16:31:27 -070097#include "DumpstateService.h"
Colin Crossf45fa6b2012-03-26 12:38:26 -070098#include "dumpstate.h"
Felipe Leme6e01fa62015-11-11 19:35:14 -080099
Kedar Chitnis9fd8c052021-11-16 09:09:22 +0000100namespace dumpstate_hal_hidl_1_0 = android::hardware::dumpstate::V1_0;
101namespace dumpstate_hal_hidl = android::hardware::dumpstate::V1_1;
102namespace dumpstate_hal_aidl = aidl::android::hardware::dumpstate;
103
Vishnu Naire97d6122018-01-18 13:58:56 -0800104using ::std::literals::chrono_literals::operator""ms;
105using ::std::literals::chrono_literals::operator""s;
Rhed Jao5377d792020-07-16 17:37:39 +0800106using ::std::placeholders::_1;
Steven Morelandcb7ef822016-11-29 13:20:37 -0800107
Felipe Leme47e9be22016-12-21 15:37:07 -0800108// TODO: remove once moved to namespace
Vishnu Naire97d6122018-01-18 13:58:56 -0800109using android::defaultServiceManager;
110using android::Dumpsys;
111using android::INVALID_OPERATION;
112using android::IServiceManager;
113using android::OK;
114using android::sp;
115using android::status_t;
116using android::String16;
117using android::String8;
118using android::TIMED_OUT;
119using android::UNKNOWN_ERROR;
120using android::Vector;
Nandana Dutt979388e2018-11-30 16:48:55 +0000121using android::base::StringPrintf;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000122using android::os::IDumpstateListener;
Felipe Leme47e9be22016-12-21 15:37:07 -0800123using android::os::dumpstate::CommandOptions;
124using android::os::dumpstate::DumpFileToFd;
Rhed Jao5377d792020-07-16 17:37:39 +0800125using android::os::dumpstate::DumpPool;
Vishnu Naire97d6122018-01-18 13:58:56 -0800126using android::os::dumpstate::PropertiesHelper;
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800127using android::os::dumpstate::TaskQueue;
Chris Morinbc223142022-02-04 14:17:11 -0800128using android::os::dumpstate::WaitForTask;
Felipe Leme47e9be22016-12-21 15:37:07 -0800129
Abhijeet Kaurcf234e82019-07-01 14:53:55 +0100130// Keep in sync with
131// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
132static const int TRACE_DUMP_TIMEOUT_MS = 10000; // 10 seconds
133
134/* Most simple commands have 10 as timeout, so 5 is a good estimate */
135static const int32_t WEIGHT_FILE = 5;
136
137// TODO: temporary variables and functions used during C++ refactoring
138static Dumpstate& ds = Dumpstate::GetInstance();
139static int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Nandana Dutt8d945c02019-08-14 13:30:07 +0100140 const CommandOptions& options = CommandOptions::DEFAULT,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800141 bool verbose_duration = false, int out_fd = STDOUT_FILENO) {
142 return ds.RunCommand(title, full_command, options, verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +0100143}
144
145// Reasonable value for max stats.
146static const int STATS_MAX_N_RUNS = 1000;
147static const long STATS_MAX_AVERAGE = 100000;
148
149CommandOptions Dumpstate::DEFAULT_DUMPSYS = CommandOptions::WithTimeout(30).Build();
150
Nandana Duttd2f5f082019-01-18 17:13:52 +0000151typedef Dumpstate::ConsentCallback::ConsentResult UserConsentResult;
152
Colin Crossf45fa6b2012-03-26 12:38:26 -0700153/* read before root is shed */
154static char cmdline_buf[16384] = "(unknown)";
Yi Kong19d5c002018-07-20 13:39:55 -0700155static const char *dump_traces_path = nullptr;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000156static const uint64_t USER_CONSENT_TIMEOUT_MS = 30 * 1000;
Hunter Knepshield70610fa2020-01-03 15:27:33 -0800157// Because telephony reports are significantly faster to collect (< 10 seconds vs. > 2 minutes),
158// it's often the case that they time out far too quickly for consent with such a hefty dialog for
159// the user to read. For telephony reports only, we increase the default timeout to 2 minutes to
160// roughly match full reports' durations.
161static const uint64_t TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS = 2 * 60 * 1000;
Colin Crossf45fa6b2012-03-26 12:38:26 -0700162
Felipe Leme1d486fe2016-10-14 18:06:47 -0700163// TODO: variables and functions below should be part of dumpstate object
164
Felipe Leme635ca312016-01-05 14:23:02 -0800165static std::set<std::string> mount_points;
166void add_mountinfo();
Felipe Leme78f2c862015-12-21 09:55:22 -0800167
Todd Poynor2a83daa2013-11-22 15:44:22 -0800168#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
Mark Salyzyn7d0a7622016-06-24 14:06:15 -0700169#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
Wei Wang509bb5d2017-06-09 14:42:12 -0700170#define BLK_DEV_SYS_DIR "/sys/block"
Todd Poynor2a83daa2013-11-22 15:44:22 -0800171
Felipe Lemee82a27d2016-01-05 13:35:44 -0800172#define RECOVERY_DIR "/cache/recovery"
Mark Salyzynd6ab0112016-03-25 12:56:39 -0700173#define RECOVERY_DATA_DIR "/data/misc/recovery"
Tianjie Xu75d53362018-04-11 16:42:28 -0700174#define UPDATE_ENGINE_LOG_DIR "/data/misc/update_engine_log"
Kelvin Zhang6eaa0f92022-09-12 09:29:19 -0700175#define UPDATE_ENGINE_PREF_DIR "/data/misc/update_engine/prefs"
Mark Salyzyn4d42dea2016-04-01 10:03:14 -0700176#define LOGPERSIST_DATA_DIR "/data/misc/logd"
Jerry Changa1df8a92020-01-02 16:03:39 +0800177#define PREREBOOT_DATA_DIR "/data/misc/prereboot"
David Brazdild2991962016-06-03 14:40:44 +0100178#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
179#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
Benedict Wong8f9d8a42019-01-03 16:19:38 -0800180#define XFRM_STAT_PROC_FILE "/proc/net/xfrm_stat"
Erik Kline08165202016-05-30 11:55:44 +0900181#define WLUTIL "/vendor/xbin/wlutil"
Vishnu Nair36b4cdb2017-11-17 10:27:05 -0800182#define WMTRACE_DATA_DIR "/data/misc/wmtrace"
Yifan Hong3945e1b2019-10-29 12:59:23 -0700183#define OTA_METADATA_DIR "/metadata/ota"
Yifan Hong0efa7972020-02-03 16:45:02 -0800184#define SNAPSHOTCTL_LOG_DIR "/data/misc/snapshotctl_log"
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +0900185#define LINKERCONFIG_DIR "/linkerconfig"
Calin Juravlef84d3692020-04-28 15:31:12 -0700186#define PACKAGE_DEX_USE_LIST "/data/system/package-dex-usage.list"
Primiano Tuccifaaaafb2021-01-14 12:26:29 +0000187#define SYSTEM_TRACE_SNAPSHOT "/data/misc/perfetto-traces/bugreport/systrace.pftrace"
Li Li2eedd412021-06-30 15:11:53 -0700188#define CGROUPFS_DIR "/sys/fs/cgroup"
Mårten Kongstad60195a72022-09-20 14:14:20 +0200189#define SDK_EXT_INFO "/apex/com.android.sdkext/bin/derive_sdk"
Jeff Sharkey9df29d52023-02-06 14:26:30 -0700190#define DROPBOX_DIR "/data/system/dropbox"
Mårten Kongstad5ad813f2023-09-28 10:09:18 +0200191#define PRINT_FLAGS "/system/bin/printflags"
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700192
Narayan Kamath8f788292017-05-25 13:20:39 +0100193// TODO(narayan): Since this information has to be kept in sync
194// with tombstoned, we should just put it in a common header.
195//
196// File: system/core/debuggerd/tombstoned/tombstoned.cpp
Narayan Kamathbd863722017-06-01 18:50:12 +0100197static const std::string TOMBSTONE_DIR = "/data/tombstones/";
198static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
199static const std::string ANR_DIR = "/data/anr/";
200static const std::string ANR_FILE_PREFIX = "anr_";
Woody Lin20767a92022-11-29 15:50:24 +0800201static const std::string SHUTDOWN_CHECKPOINTS_DIR = "/data/system/shutdown-checkpoints/";
202static const std::string SHUTDOWN_CHECKPOINTS_FILE_PREFIX = "checkpoints-";
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700203
Felipe Lemee844a9d2016-09-21 15:01:39 -0700204// TODO: temporary variables and functions used during C++ refactoring
Nandana Dutt979388e2018-11-30 16:48:55 +0000205
Nandana Dutt5c390032019-03-12 10:52:56 +0000206#define RETURN_IF_USER_DENIED_CONSENT() \
207 if (ds.IsUserConsentDenied()) { \
208 MYLOGE("Returning early as user denied consent to share bugreport with calling app."); \
209 return Dumpstate::RunStatus::USER_CONSENT_DENIED; \
210 }
211
212// Runs func_ptr, but checks user consent before and after running it. Returns USER_CONSENT_DENIED
213// if consent is found to be denied.
214#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(func_ptr, ...) \
215 RETURN_IF_USER_DENIED_CONSENT(); \
216 func_ptr(__VA_ARGS__); \
217 RETURN_IF_USER_DENIED_CONSENT();
218
Rhed Jao5377d792020-07-16 17:37:39 +0800219// Runs func_ptr, and logs a duration report after it's finished.
220#define RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, ...) \
221 { \
222 DurationReporter duration_reporter_in_macro(log_title); \
223 func_ptr(__VA_ARGS__); \
224 }
225
226// Similar with RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK, an additional duration report
227// is output after a slow function is finished.
228#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(log_title, func_ptr, ...) \
229 RETURN_IF_USER_DENIED_CONSENT(); \
230 RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, __VA_ARGS__); \
231 RETURN_IF_USER_DENIED_CONSENT();
232
Chris Morinbc223142022-02-04 14:17:11 -0800233#define WAIT_TASK_WITH_CONSENT_CHECK(future) \
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800234 RETURN_IF_USER_DENIED_CONSENT(); \
Chris Morinbc223142022-02-04 14:17:11 -0800235 WaitForTask(future); \
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800236 RETURN_IF_USER_DENIED_CONSENT();
237
Sahana Raof35ed432019-07-12 10:47:52 +0100238static const char* WAKE_LOCK_NAME = "dumpstate_wakelock";
239
Rhed Jao5377d792020-07-16 17:37:39 +0800240// Names of parallel tasks, they are used for the DumpPool to identify the dump
241// task and the log title of the duration report.
242static const std::string DUMP_TRACES_TASK = "DUMP TRACES";
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800243static const std::string DUMP_INCIDENT_REPORT_TASK = "INCIDENT REPORT";
Aaron Huang24d215d2022-04-27 18:51:16 +0800244static const std::string DUMP_NETSTATS_PROTO_TASK = "DUMP NETSTATS PROTO";
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800245static const std::string DUMP_HALS_TASK = "DUMP HALS";
246static const std::string DUMP_BOARD_TASK = "dumpstate_board()";
Rhed Jaoe017f982020-07-21 17:58:41 +0800247static const std::string DUMP_CHECKINS_TASK = "DUMP CHECKINS";
Kean Mariotti306633e2022-09-05 16:30:47 +0000248static const std::string POST_PROCESS_UI_TRACES_TASK = "POST-PROCESS UI TRACES";
Rhed Jao5377d792020-07-16 17:37:39 +0800249
Nandana Dutt979388e2018-11-30 16:48:55 +0000250namespace android {
251namespace os {
252namespace {
253
254static int Open(std::string path, int flags, mode_t mode = 0) {
255 int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
256 if (fd == -1) {
257 MYLOGE("open(%s, %s)\n", path.c_str(), strerror(errno));
258 }
259 return fd;
260}
261
mhasank2d75c442020-06-11 15:05:25 -0700262static int OpenForWrite(std::string path) {
263 return Open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
264 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
265}
Nandana Dutt979388e2018-11-30 16:48:55 +0000266
267static int OpenForRead(std::string path) {
268 return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
269}
270
271bool CopyFile(int in_fd, int out_fd) {
272 char buf[4096];
273 ssize_t byte_count;
274 while ((byte_count = TEMP_FAILURE_RETRY(read(in_fd, buf, sizeof(buf)))) > 0) {
275 if (!android::base::WriteFully(out_fd, buf, byte_count)) {
276 return false;
277 }
278 }
279 return (byte_count != -1);
280}
281
282static bool CopyFileToFd(const std::string& input_file, int out_fd) {
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000283 MYLOGD("Going to copy file (%s) to %d\n", input_file.c_str(), out_fd);
Nandana Dutt979388e2018-11-30 16:48:55 +0000284
285 // Obtain a handle to the source file.
286 android::base::unique_fd in_fd(OpenForRead(input_file));
287 if (out_fd != -1 && in_fd.get() != -1) {
288 if (CopyFile(in_fd.get(), out_fd)) {
289 return true;
290 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000291 MYLOGE("Failed to copy file: %s\n", strerror(errno));
Nandana Dutt979388e2018-11-30 16:48:55 +0000292 }
293 return false;
294}
295
Nandana Duttd2f5f082019-01-18 17:13:52 +0000296static bool UnlinkAndLogOnError(const std::string& file) {
Nandana Dutt8ae16e62020-03-27 10:20:22 +0000297 if (file.empty()) {
298 return false;
299 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000300 if (unlink(file.c_str())) {
301 MYLOGE("Failed to unlink file (%s): %s\n", file.c_str(), strerror(errno));
Nandana Duttd2f5f082019-01-18 17:13:52 +0000302 return false;
303 }
304 return true;
305}
Nandana Dutt979388e2018-11-30 16:48:55 +0000306
Nikita Ioffea325a572019-05-16 19:49:47 +0100307int64_t GetModuleMetadataVersion() {
308 auto binder = defaultServiceManager()->getService(android::String16("package_native"));
309 if (binder == nullptr) {
310 MYLOGE("Failed to retrieve package_native service");
311 return 0L;
312 }
313 auto package_service = android::interface_cast<content::pm::IPackageManagerNative>(binder);
314 std::string package_name;
315 auto status = package_service->getModuleMetadataPackageName(&package_name);
316 if (!status.isOk()) {
317 MYLOGE("Failed to retrieve module metadata package name: %s", status.toString8().c_str());
318 return 0L;
319 }
Nandana Duttdb379fa2019-10-09 16:54:41 +0100320 MYLOGD("Module metadata package name: %s\n", package_name.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100321 int64_t version_code;
322 status = package_service->getVersionCodeForPackage(android::String16(package_name.c_str()),
323 &version_code);
324 if (!status.isOk()) {
325 MYLOGE("Failed to retrieve module metadata version: %s", status.toString8().c_str());
326 return 0L;
327 }
328 return version_code;
329}
330
mhasank2d75c442020-06-11 15:05:25 -0700331static bool PathExists(const std::string& path) {
332 struct stat sb;
333 return stat(path.c_str(), &sb) == 0;
334}
335
336static bool CopyFileToFile(const std::string& input_file, const std::string& output_file) {
337 if (input_file == output_file) {
338 MYLOGD("Skipping copying bugreport file since the destination is the same (%s)\n",
339 output_file.c_str());
340 return false;
341 }
342 else if (PathExists(output_file)) {
343 MYLOGD("Cannot overwrite an existing file (%s)\n", output_file.c_str());
344 return false;
345 }
346
347 MYLOGD("Going to copy bugreport file (%s) to %s\n", input_file.c_str(), output_file.c_str());
348 android::base::unique_fd out_fd(OpenForWrite(output_file));
349 return CopyFileToFd(input_file, out_fd.get());
350}
351
Nandana Dutt979388e2018-11-30 16:48:55 +0000352} // namespace
353} // namespace os
354} // namespace android
355
Felipe Leme678727a2016-09-21 17:22:11 -0700356static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
Felipe Lemebda15a02016-11-16 17:48:25 -0800357 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
Rhed Jaoe017f982020-07-21 17:58:41 +0800358 long dumpsysTimeoutMs = 0, int out_fd = STDOUT_FILENO) {
359 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs, out_fd);
360}
361static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
362 int out_fd) {
363 return ds.RunDumpsys(title, dumpsysArgs, Dumpstate::DEFAULT_DUMPSYS, 0, out_fd);
Felipe Leme678727a2016-09-21 17:22:11 -0700364}
365static int DumpFile(const std::string& title, const std::string& path) {
366 return ds.DumpFile(title, path);
367}
Felipe Lemee82a27d2016-01-05 13:35:44 -0800368
Felipe Lemee844a9d2016-09-21 15:01:39 -0700369// Relative directory (inside the zip) for all files copied as-is into the bugreport.
370static const std::string ZIP_ROOT_DIR = "FS";
371
Vishnu Naire97d6122018-01-18 13:58:56 -0800372static const std::string kProtoPath = "proto/";
373static const std::string kProtoExt = ".proto";
Jie Song9fbfad02017-06-20 16:29:42 -0700374static const std::string kDumpstateBoardFiles[] = {
375 "dumpstate_board.txt",
Felipe Leme95d6ca52017-08-01 16:35:56 -0700376 "dumpstate_board.bin"
Jie Song9fbfad02017-06-20 16:29:42 -0700377};
378static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
379
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700380static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Lemed071c682016-10-20 16:48:00 -0700381static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700382
Felipe Lemef0292972016-11-22 13:57:05 -0800383static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
384
Narayan Kamath8f788292017-05-25 13:20:39 +0100385/*
Narayan Kamathbd863722017-06-01 18:50:12 +0100386 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
Rhed Jao01dc0c62020-06-03 17:13:30 +0800387 * The returned vector is sorted by the mtimes of the dumps with descending
Chris Morinc2cba7a2022-02-01 17:06:50 -0800388 * order.
Narayan Kamath8f788292017-05-25 13:20:39 +0100389 */
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700390static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
Chris Morinc2cba7a2022-02-01 17:06:50 -0800391 const std::string& file_prefix) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100392 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100393
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700394 if (dump_dir == nullptr) {
395 MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno));
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700396 return std::vector<DumpData>();
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700397 }
398
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700399 std::vector<DumpData> dump_data;
Narayan Kamathbd863722017-06-01 18:50:12 +0100400 struct dirent* entry = nullptr;
401 while ((entry = readdir(dump_dir.get()))) {
402 if (entry->d_type != DT_REG) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100403 continue;
404 }
405
Narayan Kamathbd863722017-06-01 18:50:12 +0100406 const std::string base_name(entry->d_name);
407 if (base_name.find(file_prefix) != 0) {
408 continue;
409 }
410
411 const std::string abs_path = dir_path + base_name;
412 android::base::unique_fd fd(
413 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
414 if (fd == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700415 MYLOGW("Unable to open dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamathbd863722017-06-01 18:50:12 +0100416 break;
417 }
418
419 struct stat st = {};
420 if (fstat(fd, &st) == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700421 MYLOGW("Unable to stat dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamath8f788292017-05-25 13:20:39 +0100422 continue;
423 }
424
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700425 dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700426 }
Rhed Jao01dc0c62020-06-03 17:13:30 +0800427 if (!dump_data.empty()) {
428 std::sort(dump_data.begin(), dump_data.end(),
429 [](const auto& a, const auto& b) { return a.mtime > b.mtime; });
430 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100431
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700432 return dump_data;
Narayan Kamath8f788292017-05-25 13:20:39 +0100433}
434
Narayan Kamathbd863722017-06-01 18:50:12 +0100435static bool AddDumps(const std::vector<DumpData>::const_iterator start,
436 const std::vector<DumpData>::const_iterator end,
437 const char* type_name, const bool add_to_zip) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100438 bool dumped = false;
Narayan Kamathbd863722017-06-01 18:50:12 +0100439 for (auto it = start; it != end; ++it) {
440 const std::string& name = it->name;
441 const int fd = it->fd;
Narayan Kamath8f788292017-05-25 13:20:39 +0100442 dumped = true;
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100443
444 // Seek to the beginning of the file before dumping any data. A given
445 // DumpData entry might be dumped multiple times in the report.
446 //
447 // For example, the most recent ANR entry is dumped to the body of the
448 // main entry and it also shows up as a separate entry in the bugreport
449 // ZIP file.
450 if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) {
451 MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(),
452 strerror(errno));
453 }
454
Chris Morinc2cba7a2022-02-01 17:06:50 -0800455 if (add_to_zip) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800456 if (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd, /* timeout = */ 0ms) != OK) {
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100457 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100458 }
459 } else {
460 dump_file_from_fd(type_name, name.c_str(), fd);
461 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100462 }
463
464 return dumped;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700465}
466
Felipe Leme635ca312016-01-05 14:23:02 -0800467// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700468void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800469 char path[PATH_MAX];
470
471 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
472 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700473 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800474 char linkname[PATH_MAX];
475 ssize_t r = readlink(path, linkname, PATH_MAX);
476 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800477 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800478 return;
479 }
480 linkname[r] = '\0';
481
482 if (mount_points.find(linkname) == mount_points.end()) {
483 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700484 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700485 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
Felipe Leme635ca312016-01-05 14:23:02 -0800486 mount_points.insert(linkname);
487 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800488 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800489 }
490 }
491}
492
493void add_mountinfo() {
Felipe Leme678727a2016-09-21 17:22:11 -0700494 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800495 mount_points.clear();
Felipe Leme46b85da2016-11-21 17:40:45 -0800496 DurationReporter duration_reporter(title, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700497 for_each_pid(do_mountinfo, nullptr);
498 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800499}
500
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700501static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
502{
503 DIR *d;
504 struct dirent *de;
505 char path[PATH_MAX];
506
507 d = opendir(driverpath);
Yi Kong19d5c002018-07-20 13:39:55 -0700508 if (d == nullptr) {
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700509 return;
510 }
511
512 while ((de = readdir(d))) {
513 if (de->d_type != DT_LNK) {
514 continue;
515 }
516 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700517 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700518 }
519
520 closedir(d);
521}
522
Mark Salyzyn326842f2015-04-30 09:49:41 -0700523static bool skip_not_stat(const char *path) {
524 static const char stat[] = "/stat";
525 size_t len = strlen(path);
526 if (path[len - 1] == '/') { /* Directory? */
527 return false;
528 }
529 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
530}
531
Jeff Sharkey9df29d52023-02-06 14:26:30 -0700532static bool skip_wtf_strictmode(const char *path) {
533 if (strstr(path, "_wtf")) {
534 return true;
535 } else if (strstr(path, "_strictmode")) {
536 return true;
537 }
538 return false;
539}
540
Felipe Leme4c2d6632016-09-28 14:32:00 -0700541static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800542 return false;
543}
544
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700545unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700546
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800547//
548// stat offsets
549// Name units description
550// ---- ----- -----------
551// read I/Os requests number of read I/Os processed
552#define __STAT_READ_IOS 0
553// read merges requests number of read I/Os merged with in-queue I/O
554#define __STAT_READ_MERGES 1
555// read sectors sectors number of sectors read
556#define __STAT_READ_SECTORS 2
557// read ticks milliseconds total wait time for read requests
558#define __STAT_READ_TICKS 3
559// write I/Os requests number of write I/Os processed
560#define __STAT_WRITE_IOS 4
561// write merges requests number of write I/Os merged with in-queue I/O
562#define __STAT_WRITE_MERGES 5
563// write sectors sectors number of sectors written
564#define __STAT_WRITE_SECTORS 6
565// write ticks milliseconds total wait time for write requests
566#define __STAT_WRITE_TICKS 7
567// in_flight requests number of I/Os currently in flight
568#define __STAT_IN_FLIGHT 8
569// io_ticks milliseconds total time this block device has been active
570#define __STAT_IO_TICKS 9
571// time_in_queue milliseconds total wait time for all requests
572#define __STAT_IN_QUEUE 10
573#define __STAT_NUMBER_FIELD 11
574//
575// read I/Os, write I/Os
576// =====================
577//
578// These values increment when an I/O request completes.
579//
580// read merges, write merges
581// =========================
582//
583// These values increment when an I/O request is merged with an
584// already-queued I/O request.
585//
586// read sectors, write sectors
587// ===========================
588//
589// These values count the number of sectors read from or written to this
590// block device. The "sectors" in question are the standard UNIX 512-byte
591// sectors, not any device- or filesystem-specific block size. The
592// counters are incremented when the I/O completes.
593#define SECTOR_SIZE 512
594//
595// read ticks, write ticks
596// =======================
597//
598// These values count the number of milliseconds that I/O requests have
599// waited on this block device. If there are multiple I/O requests waiting,
600// these values will increase at a rate greater than 1000/second; for
601// example, if 60 read requests wait for an average of 30 ms, the read_ticks
602// field will increase by 60*30 = 1800.
603//
604// in_flight
605// =========
606//
607// This value counts the number of I/O requests that have been issued to
608// the device driver but have not yet completed. It does not include I/O
609// requests that are in the queue but not yet issued to the device driver.
610//
611// io_ticks
612// ========
613//
614// This value counts the number of milliseconds during which the device has
615// had I/O requests queued.
616//
617// time_in_queue
618// =============
619//
620// This value counts the number of milliseconds that I/O requests have waited
621// on this block device. If there are multiple I/O requests waiting, this
622// value will increase as the product of the number of milliseconds times the
623// number of requests waiting (see "read ticks" above for an example).
624#define S_TO_MS 1000
625//
626
Mark Salyzyn326842f2015-04-30 09:49:41 -0700627static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800628 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700629 bool z;
Yi Kong19d5c002018-07-20 13:39:55 -0700630 char *cp, *buffer = nullptr;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700631 size_t i = 0;
Josh Gao7c4258c2018-06-25 13:40:08 -0700632 FILE *fp = fdopen(dup(fd), "rb");
Mark Salyzyn326842f2015-04-30 09:49:41 -0700633 getline(&buffer, &i, fp);
634 fclose(fp);
635 if (!buffer) {
636 return -errno;
637 }
638 i = strlen(buffer);
639 while ((i > 0) && (buffer[i - 1] == '\n')) {
640 buffer[--i] = '\0';
641 }
642 if (!*buffer) {
643 free(buffer);
644 return 0;
645 }
646 z = true;
647 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800648 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700649 if (fields[i] != 0) {
650 z = false;
651 }
652 }
653 if (z) { /* never accessed */
654 free(buffer);
655 return 0;
656 }
657
Wei Wang509bb5d2017-06-09 14:42:12 -0700658 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
659 path += sizeof(BLK_DEV_SYS_DIR) - 1;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700660 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700661
662 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
663 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
664 "W-wait", "in-fli", "activ", "T-wait", path, buffer);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700665 free(buffer);
666
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800667 if (fields[__STAT_IO_TICKS]) {
668 unsigned long read_perf = 0;
669 unsigned long read_ios = 0;
670 if (fields[__STAT_READ_TICKS]) {
671 unsigned long long divisor = fields[__STAT_READ_TICKS]
672 * fields[__STAT_IO_TICKS];
673 read_perf = ((unsigned long long)SECTOR_SIZE
674 * fields[__STAT_READ_SECTORS]
675 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
676 / divisor;
677 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
678 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
679 / divisor;
680 }
681
682 unsigned long write_perf = 0;
683 unsigned long write_ios = 0;
684 if (fields[__STAT_WRITE_TICKS]) {
685 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
686 * fields[__STAT_IO_TICKS];
687 write_perf = ((unsigned long long)SECTOR_SIZE
688 * fields[__STAT_WRITE_SECTORS]
689 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
690 / divisor;
691 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
692 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
693 / divisor;
694 }
695
696 unsigned queue = (fields[__STAT_IN_QUEUE]
697 + (fields[__STAT_IO_TICKS] >> 1))
698 / fields[__STAT_IO_TICKS];
699
700 if (!write_perf && !write_ios) {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700701 printf("%-30s: perf(ios) rd: %luKB/s(%lu/s) q: %u\n", path, read_perf, read_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800702 } else {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700703 printf("%-30s: perf(ios) rd: %luKB/s(%lu/s) wr: %luKB/s(%lu/s) q: %u\n", path, read_perf,
Felipe Lemed8b94e52016-12-08 10:21:44 -0800704 read_ios, write_perf, write_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800705 }
706
707 /* bugreport timeout factor adjustment */
708 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
709 worst_write_perf = write_perf;
710 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700711 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700712 return 0;
713}
714
Yao Chenbe3bbc12018-01-17 16:31:10 -0800715static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
716
Tom Cherryf4472f32020-08-05 09:31:17 -0700717// Returns the actual readable size of the given buffer or -1 on error.
718static long logcat_buffer_readable_size(const std::string& buffer) {
719 std::unique_ptr<logger_list, decltype(&android_logger_list_free)> logger_list{
720 android_logger_list_alloc(0, 0, 0), &android_logger_list_free};
721 auto logger = android_logger_open(logger_list.get(), android_name_to_log_id(buffer.c_str()));
722
723 return android_logger_get_log_readable_size(logger);
724}
725
726// Returns timeout in ms to read a list of buffers.
Yao Chenbe3bbc12018-01-17 16:31:10 -0800727static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
728 unsigned long timeout_ms = 0;
729 for (const auto& buffer : buffers) {
Tom Cherryf4472f32020-08-05 09:31:17 -0700730 long readable_size = logcat_buffer_readable_size(buffer);
731 if (readable_size > 0) {
732 // Engineering margin is ten-fold our guess.
733 timeout_ms += 10 * (readable_size + worst_write_perf) / worst_write_perf;
734 }
Yao Chenbe3bbc12018-01-17 16:31:10 -0800735 }
736 return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700737}
738
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800739// Opens a socket and returns its file descriptor.
740static int open_socket(const char* service);
741
Nandana Duttd2f5f082019-01-18 17:13:52 +0000742Dumpstate::ConsentCallback::ConsentCallback() : result_(UNAVAILABLE), start_time_(Nanotime()) {
743}
744
745android::binder::Status Dumpstate::ConsentCallback::onReportApproved() {
746 std::lock_guard<std::mutex> lock(lock_);
747 result_ = APPROVED;
748 MYLOGD("User approved consent to share bugreport\n");
Paul Chang0d2aad72020-02-13 20:04:03 +0800749
750 // Maybe copy screenshot so calling app can display the screenshot to the user as soon as
751 // consent is granted.
752 if (ds.options_->is_screenshot_copied) {
753 return android::binder::Status::ok();
754 }
755
756 if (!ds.options_->do_screenshot || ds.options_->screenshot_fd.get() == -1 ||
757 !ds.do_early_screenshot_) {
758 return android::binder::Status::ok();
759 }
760
761 bool copy_succeeded = android::os::CopyFileToFd(ds.screenshot_path_,
762 ds.options_->screenshot_fd.get());
763 ds.options_->is_screenshot_copied = copy_succeeded;
764 if (copy_succeeded) {
765 android::os::UnlinkAndLogOnError(ds.screenshot_path_);
766 }
Nandana Duttd2f5f082019-01-18 17:13:52 +0000767 return android::binder::Status::ok();
768}
769
770android::binder::Status Dumpstate::ConsentCallback::onReportDenied() {
771 std::lock_guard<std::mutex> lock(lock_);
772 result_ = DENIED;
773 MYLOGW("User denied consent to share bugreport\n");
774 return android::binder::Status::ok();
775}
776
777UserConsentResult Dumpstate::ConsentCallback::getResult() {
778 std::lock_guard<std::mutex> lock(lock_);
779 return result_;
780}
781
782uint64_t Dumpstate::ConsentCallback::getElapsedTimeMs() const {
Hunter Knepshieldf0a39052020-01-03 14:53:04 -0800783 return (Nanotime() - start_time_) / NANOS_PER_MILLI;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000784}
785
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700786void Dumpstate::PrintHeader() const {
Mårten Kongstad60195a72022-09-20 14:14:20 +0200787 std::string build, fingerprint, radio, bootloader, network, sdkversion;
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700788 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700789
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700790 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
791 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700792 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
793 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
794 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
Mårten Kongstad60195a72022-09-20 14:14:20 +0200795 sdkversion = android::base::GetProperty("ro.build.version.sdk", "(unknown)");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700796 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
Colin Crossf45fa6b2012-03-26 12:38:26 -0700797
Felipe Lemed8b94e52016-12-08 10:21:44 -0800798 printf("========================================================\n");
799 printf("== dumpstate: %s\n", date);
800 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700801
Felipe Lemed8b94e52016-12-08 10:21:44 -0800802 printf("\n");
803 printf("Build: %s\n", build.c_str());
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700804 // NOTE: fingerprint entry format is important for other tools.
Felipe Lemed8b94e52016-12-08 10:21:44 -0800805 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
806 printf("Bootloader: %s\n", bootloader.c_str());
807 printf("Radio: %s\n", radio.c_str());
808 printf("Network: %s\n", network.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100809 int64_t module_metadata_version = android::os::GetModuleMetadataVersion();
810 if (module_metadata_version != 0) {
811 printf("Module Metadata version: %" PRId64 "\n", module_metadata_version);
812 }
Mårten Kongstad60195a72022-09-20 14:14:20 +0200813 printf("Android SDK version: %s\n", sdkversion.c_str());
814 printf("SDK extensions: ");
815 RunCommandToFd(STDOUT_FILENO, "", {SDK_EXT_INFO, "--header"},
816 CommandOptions::WithTimeout(1).Always().DropRoot().Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700817
Felipe Lemed8b94e52016-12-08 10:21:44 -0800818 printf("Kernel: ");
Felipe Lemef0292972016-11-22 13:57:05 -0800819 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
Felipe Lemed8b94e52016-12-08 10:21:44 -0800820 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
Devin Moore09fde8d2023-03-21 16:28:22 +0000821 printf("Bootconfig: ");
822 DumpFileToFd(STDOUT_FILENO, "", "/proc/bootconfig");
Felipe Leme7709f8a2017-12-05 09:30:09 -0800823 printf("Uptime: ");
824 RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"},
825 CommandOptions::WithTimeout(1).Always().Build());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800826 printf("Bugreport format version: %s\n", version_.c_str());
Kevin Jeonfa64e642023-07-27 11:36:41 -0400827 printf(
828 "Dumpstate info: id=%d pid=%d dry_run=%d parallel_run=%d strict_run=%d args=%s "
829 "bugreport_mode=%s\n",
830 id_, pid_, PropertiesHelper::IsDryRun(), PropertiesHelper::IsParallelRun(),
831 PropertiesHelper::IsStrictRun(), options_->args.c_str(),
832 options_->bugreport_mode_string.c_str());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800833 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800834}
835
Felipe Leme24b66ee2016-06-16 10:55:26 -0700836// List of file extensions that can cause a zip file attachment to be rejected by some email
837// service providers.
838static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
839 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
840 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
841 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
842};
843
Vishnu Naire97d6122018-01-18 13:58:56 -0800844status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd,
845 std::chrono::milliseconds timeout = 0ms) {
Felipe Leme24b66ee2016-06-16 10:55:26 -0700846 std::string valid_name = entry_name;
847
848 // Rename extension if necessary.
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -0700849 size_t idx = entry_name.rfind('.');
Felipe Leme24b66ee2016-06-16 10:55:26 -0700850 if (idx != std::string::npos) {
851 std::string extension = entry_name.substr(idx);
852 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
853 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
854 valid_name = entry_name + ".renamed";
855 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
856 }
857 }
858
Felipe Leme6fe9db62016-02-12 09:04:16 -0800859 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
860 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Kevin Jeon9bbe0ac2022-05-05 22:05:43 +0000861 size_t flags = ZipWriter::kCompress | ZipWriter::kDefaultCompression;
862 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), flags,
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700863 get_mtime(fd, ds.now_));
Felipe Leme1d486fe2016-10-14 18:06:47 -0700864 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700865 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700866 ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800867 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800868 }
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000869 bool finished_entry = false;
870 auto finish_entry = [this, &finished_entry] {
871 if (!finished_entry) {
872 // This should only be called when we're going to return an earlier error,
873 // which would've been logged. This may imply the file is already corrupt
874 // and any further logging from FinishEntry is more likely to mislead than
875 // not.
876 this->zip_writer_->FinishEntry();
877 }
878 };
879 auto scope_guard = android::base::make_scope_guard(finish_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -0800880 auto start = std::chrono::steady_clock::now();
881 auto end = start + timeout;
882 struct pollfd pfd = {fd, POLLIN};
Felipe Lemee82a27d2016-01-05 13:35:44 -0800883
Felipe Leme770410d2016-01-26 17:07:14 -0800884 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800885 while (1) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800886 if (timeout.count() > 0) {
887 // lambda to recalculate the timeout.
888 auto time_left_ms = [end]() {
889 auto now = std::chrono::steady_clock::now();
890 auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
891 return std::max(diff.count(), 0LL);
892 };
893
894 int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
895 if (rc < 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000896 MYLOGE("Error in poll while adding from fd to zip entry %s:%s\n",
897 entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800898 return -errno;
899 } else if (rc == 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000900 MYLOGE("Timed out adding from fd to zip entry %s:%s Timeout:%lldms\n",
Vishnu Naire97d6122018-01-18 13:58:56 -0800901 entry_name.c_str(), strerror(errno), timeout.count());
902 return TIMED_OUT;
903 }
904 }
905
Zach Riggle22200402016-08-18 01:01:24 -0400906 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800907 if (bytes_read == 0) {
908 break;
909 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800910 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800911 return -errno;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800912 }
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700913 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800914 if (err) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700915 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800916 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800917 }
918 }
919
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700920 err = zip_writer_->FinishEntry();
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000921 finished_entry = true;
Felipe Leme1d486fe2016-10-14 18:06:47 -0700922 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700923 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800924 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800925 }
926
Vishnu Naire97d6122018-01-18 13:58:56 -0800927 return OK;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800928}
929
Felipe Leme1d486fe2016-10-14 18:06:47 -0700930bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
931 android::base::unique_fd fd(
932 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700933 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800934 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800935 return false;
936 }
937
Vishnu Naire97d6122018-01-18 13:58:56 -0800938 return (AddZipEntryFromFd(entry_name, fd.get()) == OK);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800939}
940
941/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700942static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800943 return (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) == OK) ? 0 : 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800944}
945
Felipe Leme1d486fe2016-10-14 18:06:47 -0700946void Dumpstate::AddDir(const std::string& dir, bool recursive) {
Felipe Leme678727a2016-09-21 17:22:11 -0700947 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
Felipe Leme46b85da2016-11-21 17:40:45 -0800948 DurationReporter duration_reporter(dir, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700949 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800950}
951
Felipe Leme1d486fe2016-10-14 18:06:47 -0700952bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800953 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Kevin Jeon9bbe0ac2022-05-05 22:05:43 +0000954 size_t flags = ZipWriter::kCompress | ZipWriter::kDefaultCompression;
955 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), flags, ds.now_);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700956 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700957 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700958 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800959 return false;
960 }
961
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700962 err = zip_writer_->WriteBytes(content.c_str(), content.length());
Felipe Leme1d486fe2016-10-14 18:06:47 -0700963 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700964 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700965 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800966 return false;
967 }
968
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700969 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700970 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700971 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800972 return false;
973 }
974
975 return true;
976}
977
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800978static void DoKmsg() {
979 struct stat st;
980 if (!stat(PSTORE_LAST_KMSG, &st)) {
981 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
982 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
983 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
984 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
985 } else {
986 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
987 DumpFile("LAST KMSG", "/proc/last_kmsg");
988 }
989}
990
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800991static void DoKernelLogcat() {
Yao Chenbe3bbc12018-01-17 16:31:10 -0800992 unsigned long timeout_ms = logcat_timeout({"kernel"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800993 RunCommand(
994 "KERNEL LOG",
995 {"logcat", "-b", "kernel", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
996 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
997}
998
Nandana Duttdb379fa2019-10-09 16:54:41 +0100999static void DoSystemLogcat(time_t since) {
1000 char since_str[80];
1001 strftime(since_str, sizeof(since_str), "%Y-%m-%d %H:%M:%S.000", localtime(&since));
1002
1003 unsigned long timeout_ms = logcat_timeout({"main", "system", "crash"});
1004 RunCommand("SYSTEM LOG",
1005 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v", "-T",
1006 since_str},
1007 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1008}
1009
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001010static void DoRadioLogcat() {
1011 unsigned long timeout_ms = logcat_timeout({"radio"});
1012 RunCommand(
1013 "RADIO LOG",
1014 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1015 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
1016}
1017
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001018static void DoLogcat() {
Vishnu Nair6921f802017-11-22 09:17:23 -08001019 unsigned long timeout_ms;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001020 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
1021 // calculate timeout
Yao Chenbe3bbc12018-01-17 16:31:10 -08001022 timeout_ms = logcat_timeout({"main", "system", "crash"});
Tony Makae737652017-03-30 17:47:09 +01001023 RunCommand("SYSTEM LOG",
Vishnu Nair6921f802017-11-22 09:17:23 -08001024 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1025 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -08001026 timeout_ms = logcat_timeout({"events"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001027 RunCommand(
1028 "EVENT LOG",
1029 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001030 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Yao Chenbe3bbc12018-01-17 16:31:10 -08001031 timeout_ms = logcat_timeout({"stats"});
1032 RunCommand(
1033 "STATS LOG",
1034 {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001035 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001036 DoRadioLogcat();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001037
1038 RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
1039
1040 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001041 RunCommand("LAST LOGCAT", {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable",
1042 "-v", "uid", "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001043}
1044
Mike Ma5c267872019-08-21 11:31:34 -07001045static void DumpIncidentReport() {
Mike Ma5c267872019-08-21 11:31:34 -07001046 const std::string path = ds.bugreport_internal_dir_ + "/tmp_incident_report";
1047 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1048 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1049 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1050 if (fd < 0) {
1051 MYLOGE("Could not open %s to dump incident report.\n", path.c_str());
1052 return;
1053 }
Kevin Jeonfa64e642023-07-27 11:36:41 -04001054 RunCommandToFd(fd, "", {"incident", "-u"},
1055 CommandOptions::WithTimeout(PropertiesHelper::IsStrictRun() ? 20 : 120).Build());
Mike Ma5c267872019-08-21 11:31:34 -07001056 bool empty = 0 == lseek(fd, 0, SEEK_END);
1057 if (!empty) {
1058 // Use a different name from "incident.proto"
1059 // /proto/incident.proto is reserved for incident service dump
1060 // i.e. metadata for debugging.
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001061 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "incident_report" + kProtoExt,
1062 path);
1063 } else {
1064 unlink(path.c_str());
Mike Ma5c267872019-08-21 11:31:34 -07001065 }
Mike Ma5c267872019-08-21 11:31:34 -07001066}
1067
Aaron Huang24d215d2022-04-27 18:51:16 +08001068static void DumpNetstatsProto() {
1069 const std::string path = ds.bugreport_internal_dir_ + "/tmp_netstats_proto";
1070 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1071 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1072 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1073 if (fd < 0) {
1074 MYLOGE("Could not open %s to dump netstats proto.\n", path.c_str());
1075 return;
1076 }
1077 RunCommandToFd(fd, "", {"dumpsys", "netstats", "--proto"},
Kevin Jeon2fb3dd62022-09-28 18:48:55 +00001078 CommandOptions::WithTimeout(5).Build());
Aaron Huang24d215d2022-04-27 18:51:16 +08001079 bool empty = 0 == lseek(fd, 0, SEEK_END);
1080 if (!empty) {
1081 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "netstats" + kProtoExt,
1082 path);
1083 } else {
1084 unlink(path.c_str());
1085 }
1086}
1087
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001088static void MaybeAddSystemTraceToZip() {
1089 // This function copies into the .zip the system trace that was snapshotted
1090 // by the early call to MaybeSnapshotSystemTrace(), if any background
1091 // tracing was happening.
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001092 if (!ds.has_system_trace_) {
1093 // No background trace was happening at the time dumpstate was invoked.
1094 return;
1095 }
1096 ds.AddZipEntry(
1097 ZIP_ROOT_DIR + SYSTEM_TRACE_SNAPSHOT,
1098 SYSTEM_TRACE_SNAPSHOT);
1099 android::os::UnlinkAndLogOnError(SYSTEM_TRACE_SNAPSHOT);
1100}
1101
Sunny Goyal35949782019-11-19 15:54:36 -08001102static void DumpVisibleWindowViews() {
Sunny Goyal35949782019-11-19 15:54:36 -08001103 DurationReporter duration_reporter("VISIBLE WINDOW VIEWS");
1104 const std::string path = ds.bugreport_internal_dir_ + "/tmp_visible_window_views";
1105 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1106 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1107 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1108 if (fd < 0) {
1109 MYLOGE("Could not open %s to dump visible views.\n", path.c_str());
1110 return;
1111 }
1112 RunCommandToFd(fd, "", {"cmd", "window", "dump-visible-window-views"},
Kevin Jeon774abde2022-09-28 18:20:43 +00001113 CommandOptions::WithTimeout(10).Build());
Sunny Goyal35949782019-11-19 15:54:36 -08001114 bool empty = 0 == lseek(fd, 0, SEEK_END);
1115 if (!empty) {
1116 ds.AddZipEntry("visible_windows.zip", path);
1117 } else {
1118 MYLOGW("Failed to dump visible windows\n");
1119 }
1120 unlink(path.c_str());
1121}
1122
Jayachandran Ca94c7172017-06-10 15:08:12 -07001123static void DumpIpTablesAsRoot() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001124 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
1125 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +09001126 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001127 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +09001128 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
1129 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
1130 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
1131 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001132}
1133
Woody Lin20767a92022-11-29 15:50:24 +08001134static void DumpShutdownCheckpoints() {
1135 const bool shutdown_checkpoints_dumped = AddDumps(
1136 ds.shutdown_checkpoints_.begin(), ds.shutdown_checkpoints_.end(),
1137 "SHUTDOWN CHECKPOINTS", false /* add_to_zip */);
1138 if (!shutdown_checkpoints_dumped) {
1139 printf("*** NO SHUTDOWN CHECKPOINTS to dump in %s\n\n",
1140 SHUTDOWN_CHECKPOINTS_DIR.c_str());
1141 }
1142}
1143
David Andersond9ba4752018-12-11 18:26:59 -08001144static void DumpDynamicPartitionInfo() {
1145 if (!::android::base::GetBoolProperty("ro.boot.dynamic_partitions", false)) {
1146 return;
1147 }
1148
1149 RunCommand("LPDUMP", {"lpdump", "--all"});
David Anderson6650ade2019-10-02 15:18:59 -07001150 RunCommand("DEVICE-MAPPER", {"gsid", "dump-device-mapper"});
David Andersond9ba4752018-12-11 18:26:59 -08001151}
1152
Chris Morin5a50d482022-02-01 17:41:18 -08001153static void AddAnrTraceDir(const std::string& anr_traces_dir) {
Narayan Kamath8f788292017-05-25 13:20:39 +01001154 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
1155 anr_traces_dir.c_str());
1156
1157 // If we're here, dump_traces_path will always be a temporary file
1158 // (created with mkostemp or similar) that contains dumps taken earlier
1159 // on in the process.
1160 if (dump_traces_path != nullptr) {
Chris Morin5a50d482022-02-01 17:41:18 -08001161 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
1162 dump_traces_path);
1163 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
Narayan Kamath8f788292017-05-25 13:20:39 +01001164
1165 const int ret = unlink(dump_traces_path);
1166 if (ret == -1) {
1167 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
1168 strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -07001169 }
1170 }
1171
Narayan Kamathbd863722017-06-01 18:50:12 +01001172 // Add a specific message for the first ANR Dump.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001173 if (ds.anr_data_.size() > 0) {
Chris Morin5a50d482022-02-01 17:41:18 -08001174 // The "last" ANR will always be present in the body of the main entry.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001175 AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1,
Chris Morin5a50d482022-02-01 17:41:18 -08001176 "VM TRACES AT LAST ANR", false /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001177
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001178 // Historical ANRs are always included as separate entries in the bugreport zip file.
Chris Morin5a50d482022-02-01 17:41:18 -08001179 AddDumps(ds.anr_data_.begin(), ds.anr_data_.end(),
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001180 "HISTORICAL ANR", true /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001181 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +01001182 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
1183 }
1184}
1185
1186static void AddAnrTraceFiles() {
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001187 std::string anr_traces_dir = "/data/anr";
Narayan Kamath8f788292017-05-25 13:20:39 +01001188
Chris Morin5a50d482022-02-01 17:41:18 -08001189 AddAnrTraceDir(anr_traces_dir);
Narayan Kamath8f788292017-05-25 13:20:39 +01001190
Makoto Onuki83ec63f2019-01-31 17:08:59 -08001191 RunCommand("ANR FILES", {"ls", "-lt", ANR_DIR});
1192
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001193 // Slow traces for slow operations.
Felipe Lemee184f662016-10-27 10:04:47 -07001194 struct stat st;
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001195 int i = 0;
1196 while (true) {
1197 const std::string slow_trace_path =
1198 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
1199 if (stat(slow_trace_path.c_str(), &st)) {
1200 // No traces file at this index, done with the files.
1201 break;
Felipe Lemee184f662016-10-27 10:04:47 -07001202 }
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001203 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
1204 i++;
Felipe Lemee184f662016-10-27 10:04:47 -07001205 }
1206}
1207
Wei Wang509bb5d2017-06-09 14:42:12 -07001208static void DumpBlockStatFiles() {
1209 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -07001210
Wei Wang1dc1ef52017-06-12 11:28:37 -07001211 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
1212
1213 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001214 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1215 return;
1216 }
1217
1218 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -07001219 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001220 if ((d->d_name[0] == '.')
1221 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1222 || (d->d_name[1] == '\0'))) {
1223 continue;
1224 }
1225 const std::string new_path =
1226 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1227 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1228 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1229 printf("\n");
1230 }
Wei Wang1dc1ef52017-06-12 11:28:37 -07001231 return;
Wei Wang509bb5d2017-06-09 14:42:12 -07001232}
Jayachandran Ca94c7172017-06-10 15:08:12 -07001233
1234static void DumpPacketStats() {
1235 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
Jayachandran Ca94c7172017-06-10 15:08:12 -07001236}
1237
1238static void DumpIpAddrAndRules() {
1239 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
1240 RunCommand("NETWORK INTERFACES", {"ip", "link"});
1241 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1242 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1243 RunCommand("IP RULES", {"ip", "rule", "show"});
1244 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1245}
1246
Nandana Dutt5c390032019-03-12 10:52:56 +00001247static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, int priority,
1248 std::chrono::milliseconds timeout,
1249 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001250 auto start = std::chrono::steady_clock::now();
Vishnu Naire97d6122018-01-18 13:58:56 -08001251 sp<android::IServiceManager> sm = defaultServiceManager();
1252 Dumpsys dumpsys(sm.get());
Vishnu Naire97d6122018-01-18 13:58:56 -08001253 Vector<String16> args;
1254 Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
Vishnu Naire97d6122018-01-18 13:58:56 -08001255 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1256 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001257 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001258 std::string path(title);
1259 path.append(" - ").append(String8(service).c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -08001260 size_t bytes_written = 0;
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001261 if (PropertiesHelper::IsDryRun()) {
1262 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1263 dumpsys.writeDumpFooter(STDOUT_FILENO, service, std::chrono::milliseconds(1));
1264 } else {
Devin Mooref492c1a2023-03-15 19:19:03 +00001265 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP | Dumpsys::TYPE_PID |
1266 Dumpsys::TYPE_CLIENTS | Dumpsys::TYPE_THREAD,
Devin Mooreae68df22023-02-24 20:59:51 +00001267 service, args);
1268 if (status == OK) {
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001269 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1270 std::chrono::duration<double> elapsed_seconds;
1271 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH &&
1272 service == String16("meminfo")) {
1273 // Use a longer timeout for meminfo, since 30s is not always enough.
1274 status = dumpsys.writeDump(STDOUT_FILENO, service, 60s,
1275 /* as_proto = */ false, elapsed_seconds,
1276 bytes_written);
1277 } else {
1278 status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
1279 /* as_proto = */ false, elapsed_seconds,
1280 bytes_written);
1281 }
1282 dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
1283 bool dump_complete = (status == OK);
1284 dumpsys.stopDumpThread(dump_complete);
Devin Moorecdfa4602023-03-16 20:49:39 +00001285 } else {
1286 MYLOGE("Failed to start dump thread for service: %s, status: %d",
1287 String8(service).c_str(), status);
Gavin Corkeryfac7e2b2021-07-08 22:39:02 +01001288 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001289 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001290
1291 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1292 std::chrono::steady_clock::now() - start);
1293 if (elapsed_duration > timeout) {
1294 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1295 elapsed_duration.count());
1296 break;
1297 }
1298 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001299 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001300}
1301
Vishnu Nair64afc022018-02-01 15:29:34 -08001302static void RunDumpsysText(const std::string& title, int priority,
1303 std::chrono::milliseconds timeout,
1304 std::chrono::milliseconds service_timeout) {
1305 DurationReporter duration_reporter(title);
1306 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1307 fsync(STDOUT_FILENO);
1308 RunDumpsysTextByPriority(title, priority, timeout, service_timeout);
1309}
1310
1311/* Dump all services registered with Normal or Default priority. */
Nandana Dutt5c390032019-03-12 10:52:56 +00001312static Dumpstate::RunStatus RunDumpsysTextNormalPriority(const std::string& title,
1313 std::chrono::milliseconds timeout,
1314 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001315 DurationReporter duration_reporter(title);
1316 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1317 fsync(STDOUT_FILENO);
1318 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout,
1319 service_timeout);
Nandana Dutt5c390032019-03-12 10:52:56 +00001320
1321 RETURN_IF_USER_DENIED_CONSENT();
1322
1323 return RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1324 service_timeout);
Vishnu Nair64afc022018-02-01 15:29:34 -08001325}
1326
Nandana Dutt5c390032019-03-12 10:52:56 +00001327static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priority,
1328 std::chrono::milliseconds timeout,
1329 std::chrono::milliseconds service_timeout) {
Vishnu Naire97d6122018-01-18 13:58:56 -08001330 sp<android::IServiceManager> sm = defaultServiceManager();
1331 Dumpsys dumpsys(sm.get());
1332 Vector<String16> args;
1333 Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
1334 DurationReporter duration_reporter(title);
1335
1336 auto start = std::chrono::steady_clock::now();
1337 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
1338 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001339 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001340 std::string path(kProtoPath);
1341 path.append(String8(service).c_str());
1342 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
1343 path.append("_CRITICAL");
1344 } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
1345 path.append("_HIGH");
1346 }
1347 path.append(kProtoExt);
Steven Morelandcbd69fc2021-07-20 20:45:43 +00001348 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP, service, args);
Vishnu Naire97d6122018-01-18 13:58:56 -08001349 if (status == OK) {
1350 status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
1351 bool dumpTerminated = (status == OK);
1352 dumpsys.stopDumpThread(dumpTerminated);
1353 }
1354 ZipWriter::FileEntry file_entry;
1355 ds.zip_writer_->GetLastEntry(&file_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -08001356
1357 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1358 std::chrono::steady_clock::now() - start);
1359 if (elapsed_duration > timeout) {
1360 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1361 elapsed_duration.count());
1362 break;
1363 }
1364 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001365 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001366}
1367
Nandana Dutta7db6342018-11-21 14:53:34 +00001368// Runs dumpsys on services that must dump first and will take less than 100ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001369static Dumpstate::RunStatus RunDumpsysCritical() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001370 RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1371 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Nandana Dutt5c390032019-03-12 10:52:56 +00001372
1373 RETURN_IF_USER_DENIED_CONSENT();
1374
1375 return RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1376 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Vishnu Nair780b1282017-10-10 13:57:24 -07001377}
1378
1379// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001380static Dumpstate::RunStatus RunDumpsysHigh() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001381 // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
1382 // high priority. Reduce timeout once they are able to dump in a shorter time or
1383 // moved to a parallel task.
1384 RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1385 /* timeout= */ 90s, /* service_timeout= */ 30s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001386
1387 RETURN_IF_USER_DENIED_CONSENT();
1388
1389 return RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1390 /* timeout= */ 5s, /* service_timeout= */ 1s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001391}
1392
1393// Runs dumpsys on services that must dump but can take up to 10s to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001394static Dumpstate::RunStatus RunDumpsysNormal() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001395 RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001396
1397 RETURN_IF_USER_DENIED_CONSENT();
1398
1399 return RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1400 /* timeout= */ 90s, /* service_timeout= */ 10s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001401}
1402
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001403/*
1404 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1405 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1406 * if it's not running in the parallel task.
1407 */
1408static void DumpHals(int out_fd = STDOUT_FILENO) {
Yifan Hong30528a22020-08-07 18:24:06 -07001409 RunCommand("HARDWARE HALS", {"lshal", "--all", "--types=all"},
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001410 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build(),
1411 false, out_fd);
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001412
Steven Moreland44cd9482018-01-04 16:24:13 -08001413 using android::hidl::manager::V1_0::IServiceManager;
1414 using android::hardware::defaultServiceManager;
1415
1416 sp<IServiceManager> sm = defaultServiceManager();
1417 if (sm == nullptr) {
1418 MYLOGE("Could not retrieve hwservicemanager to dump hals.\n");
1419 return;
1420 }
1421
1422 auto ret = sm->list([&](const auto& interfaces) {
1423 for (const std::string& interface : interfaces) {
1424 std::string cleanName = interface;
Steven Morelandc6b1fc22023-07-26 23:53:58 +00001425 std::replace_if(
1426 cleanName.begin(), cleanName.end(),
1427 [](char c) {
1428 return !isalnum(c) && std::string("@-_.").find(c) == std::string::npos;
1429 },
1430 '_');
Nandana Dutt979388e2018-11-30 16:48:55 +00001431 const std::string path = ds.bugreport_internal_dir_ + "/lshal_debug_" + cleanName;
Steven Moreland44cd9482018-01-04 16:24:13 -08001432
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001433 bool empty = false;
Steven Moreland44cd9482018-01-04 16:24:13 -08001434 {
1435 auto fd = android::base::unique_fd(
1436 TEMP_FAILURE_RETRY(open(path.c_str(),
1437 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1438 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1439 if (fd < 0) {
1440 MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str());
1441 continue;
1442 }
1443 RunCommandToFd(fd,
1444 "",
Steven Morelandc81cd3c2018-01-18 14:36:26 -08001445 {"lshal", "debug", "-E", interface},
Steven Moreland44cd9482018-01-04 16:24:13 -08001446 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1447
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001448 empty = 0 == lseek(fd, 0, SEEK_END);
Steven Moreland44cd9482018-01-04 16:24:13 -08001449 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001450 if (!empty) {
1451 ds.EnqueueAddZipEntryAndCleanupIfNeeded("lshal-debug/" + cleanName + ".txt",
1452 path);
1453 } else {
1454 unlink(path.c_str());
1455 }
Steven Moreland44cd9482018-01-04 16:24:13 -08001456 }
1457 });
1458
1459 if (!ret.isOk()) {
1460 MYLOGE("Could not list hals from hwservicemanager.\n");
1461 }
1462}
1463
Devin Moore8df81bb2022-06-08 22:47:02 +00001464// Dump all of the files that make up the vendor interface.
1465// See the files listed in dumpFileList() for the latest list of files.
1466static void DumpVintf() {
Devin Moore16271d92022-09-22 18:28:48 +00001467
1468 const std::string sku = android::base::GetProperty("ro.boot.product.hardware.sku", "");
1469 const auto vintfFiles = android::vintf::details::dumpFileList(sku);
Devin Moore8df81bb2022-06-08 22:47:02 +00001470 for (const auto vintfFile : vintfFiles) {
1471 struct stat st;
1472 if (stat(vintfFile.c_str(), &st) == 0) {
1473 if (S_ISDIR(st.st_mode)) {
1474 ds.AddDir(vintfFile, true /* recursive */);
1475 } else {
1476 ds.EnqueueAddZipEntryAndCleanupIfNeeded(ZIP_ROOT_DIR + vintfFile,
1477 vintfFile);
1478 }
1479 }
1480 }
1481}
1482
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001483static void DumpExternalFragmentationInfo() {
1484 struct stat st;
1485 if (stat("/proc/buddyinfo", &st) != 0) {
1486 MYLOGE("Unable to dump external fragmentation info\n");
1487 return;
1488 }
1489
1490 printf("------ EXTERNAL FRAGMENTATION INFO ------\n");
1491 std::ifstream ifs("/proc/buddyinfo");
1492 auto unusable_index_regex = std::regex{"Node\\s+([0-9]+),\\s+zone\\s+(\\S+)\\s+(.*)"};
1493 for (std::string line; std::getline(ifs, line);) {
1494 std::smatch match_results;
1495 if (std::regex_match(line, match_results, unusable_index_regex)) {
1496 std::stringstream free_pages(std::string{match_results[3]});
1497 std::vector<int> free_pages_per_order(std::istream_iterator<int>{free_pages},
1498 std::istream_iterator<int>());
1499
1500 int total_free_pages = 0;
1501 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1502 total_free_pages += (free_pages_per_order[i] * std::pow(2, i));
1503 }
1504
1505 printf("Node %s, zone %8s", match_results[1].str().c_str(),
1506 match_results[2].str().c_str());
1507
1508 int usable_free_pages = total_free_pages;
1509 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1510 auto unusable_index = (total_free_pages - usable_free_pages) /
1511 static_cast<double>(total_free_pages);
1512 printf(" %5.3f", unusable_index);
1513 usable_free_pages -= (free_pages_per_order[i] * std::pow(2, i));
1514 }
1515
1516 printf("\n");
1517 }
1518 }
1519 printf("\n");
1520}
1521
mhasankd451a472020-05-26 18:02:39 -07001522static void DumpstateLimitedOnly() {
1523 // Trimmed-down version of dumpstate to only include a whitelisted
1524 // set of logs (system log, event log, and system server / system app
1525 // crashes, and networking logs). See b/136273873 and b/138459828
1526 // for context.
1527 DurationReporter duration_reporter("DUMPSTATE");
1528 unsigned long timeout_ms;
1529 // calculate timeout
1530 timeout_ms = logcat_timeout({"main", "system", "crash"});
1531 RunCommand("SYSTEM LOG",
1532 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1533 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1534 timeout_ms = logcat_timeout({"events"});
1535 RunCommand(
1536 "EVENT LOG",
1537 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1538 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1539
1540 printf("========================================================\n");
1541 printf("== Networking Service\n");
1542 printf("========================================================\n");
1543
1544 RunDumpsys("DUMPSYS NETWORK_SERVICE_LIMITED", {"wifi", "-a"},
1545 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hugo Benichiaa162682020-10-30 23:28:56 +09001546 RunDumpsys("DUMPSYS CONNECTIVITY REQUESTS", {"connectivity", "requests"},
1547 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
mhasankd451a472020-05-26 18:02:39 -07001548
1549 printf("========================================================\n");
1550 printf("== Dropbox crashes\n");
1551 printf("========================================================\n");
1552
1553 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1554 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1555
1556 printf("========================================================\n");
1557 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1558 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1559 printf("========================================================\n");
1560 printf("== dumpstate: done (id %d)\n", ds.id_);
1561 printf("========================================================\n");
1562}
1563
Rhed Jaoe017f982020-07-21 17:58:41 +08001564/*
1565 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1566 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1567 * if it's not running in the parallel task.
1568 */
1569static void DumpCheckins(int out_fd = STDOUT_FILENO) {
1570 dprintf(out_fd, "========================================================\n");
1571 dprintf(out_fd, "== Checkins\n");
1572 dprintf(out_fd, "========================================================\n");
1573
1574 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"}, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001575 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"}, out_fd);
1576 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"}, out_fd);
1577 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"}, out_fd);
1578 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"}, out_fd);
1579}
1580
1581/*
1582 * Runs dumpsys on activity service to dump all application activities, services
1583 * and providers in the device.
1584 *
1585 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1586 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1587 * if it's not running in the parallel task.
1588 */
1589static void DumpAppInfos(int out_fd = STDOUT_FILENO) {
1590 dprintf(out_fd, "========================================================\n");
1591 dprintf(out_fd, "== Running Application Activities\n");
1592 dprintf(out_fd, "========================================================\n");
1593
1594 // The following dumpsys internally collects output from running apps, so it can take a long
1595 // time. So let's extend the timeout.
1596
1597 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1598
1599 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1600
1601 dprintf(out_fd, "========================================================\n");
1602 dprintf(out_fd, "== Running Application Services (platform)\n");
1603 dprintf(out_fd, "========================================================\n");
1604
1605 RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
1606 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1607
1608 dprintf(out_fd, "========================================================\n");
1609 dprintf(out_fd, "== Running Application Services (non-platform)\n");
1610 dprintf(out_fd, "========================================================\n");
1611
1612 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1613 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1614
1615 dprintf(out_fd, "========================================================\n");
1616 dprintf(out_fd, "== Running Application Providers (platform)\n");
1617 dprintf(out_fd, "========================================================\n");
1618
1619 RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
Rhed Jaob049f182021-01-11 21:08:43 +08001620 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001621
1622 dprintf(out_fd, "========================================================\n");
1623 dprintf(out_fd, "== Running Application Providers (non-platform)\n");
1624 dprintf(out_fd, "========================================================\n");
1625
1626 RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1627 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1628}
1629
Nandana Dutt5c390032019-03-12 10:52:56 +00001630// Dumps various things. Returns early with status USER_CONSENT_DENIED if user denies consent
1631// via the consent they are shown. Ignores other errors that occur while running various
1632// commands. The consent checking is currently done around long running tasks, which happen to
1633// be distributed fairly evenly throughout the function.
Kean Mariotti306633e2022-09-05 16:30:47 +00001634Dumpstate::RunStatus Dumpstate::dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001635 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001636
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001637 // Enqueue slow functions into the thread pool, if the parallel run is enabled.
Aaron Huang24d215d2022-04-27 18:51:16 +08001638 std::future<std::string> dump_hals, dump_incident_report, dump_board, dump_checkins,
Kean Mariotti306633e2022-09-05 16:30:47 +00001639 dump_netstats_report, post_process_ui_traces;
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001640 if (ds.dump_pool_) {
1641 // Pool was shutdown in DumpstateDefaultAfterCritical method in order to
Kean Mariotti306633e2022-09-05 16:30:47 +00001642 // drop root user. Restarts it.
1643 ds.dump_pool_->start(/* thread_counts = */3);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001644
Chris Morinbc223142022-02-04 14:17:11 -08001645 dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
1646 dump_incident_report = ds.dump_pool_->enqueueTask(
1647 DUMP_INCIDENT_REPORT_TASK, &DumpIncidentReport);
Aaron Huang24d215d2022-04-27 18:51:16 +08001648 dump_netstats_report = ds.dump_pool_->enqueueTask(
1649 DUMP_NETSTATS_PROTO_TASK, &DumpNetstatsProto);
Chris Morinbc223142022-02-04 14:17:11 -08001650 dump_board = ds.dump_pool_->enqueueTaskWithFd(
1651 DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
1652 dump_checkins = ds.dump_pool_->enqueueTaskWithFd(DUMP_CHECKINS_TASK, &DumpCheckins, _1);
Kean Mariotti306633e2022-09-05 16:30:47 +00001653 post_process_ui_traces = ds.dump_pool_->enqueueTask(
1654 POST_PROCESS_UI_TRACES_TASK, &Dumpstate::MaybePostProcessUiTraces, &ds);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001655 }
1656
Nandana Dutt5c390032019-03-12 10:52:56 +00001657 // Dump various things. Note that anything that takes "long" (i.e. several seconds) should
1658 // check intermittently (if it's intrerruptable like a foreach on pids) and/or should be wrapped
1659 // in a consent check (via RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK).
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001660 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001661 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001662 DumpBlockStatFiles();
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001663 DumpFile("MEMORY INFO", "/proc/meminfo");
1664 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001665 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001666
Kevin Jeon947922b2022-09-21 00:29:18 +00001667 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "BUGREPORT_PROCDUMP", {"bugreport_procdump"},
1668 CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001669
Sunny Goyal35949782019-11-19 15:54:36 -08001670 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpVisibleWindowViews);
1671
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001672 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1673 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1674 DumpFile("SLAB INFO", "/proc/slabinfo");
1675 DumpFile("ZONEINFO", "/proc/zoneinfo");
1676 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1677 DumpFile("BUDDYINFO", "/proc/buddyinfo");
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001678 DumpExternalFragmentationInfo();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001679
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001680 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001681
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001682 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001683 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001684
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001685 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001686 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_hals));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001687 } else {
1688 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_HALS_TASK, DumpHals);
1689 }
Steven Moreland81b429e2017-01-31 19:50:46 -08001690
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001691 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001692 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001693 struct stat s;
1694 if (stat("/proc/modules", &s) != 0) {
1695 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1696 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001697 RunCommand("LSMOD", {"lsmod"});
Woody Linc198f252021-05-04 16:37:11 +08001698 RunCommand("MODULES INFO",
1699 {"sh", "-c", "cat /proc/modules | cut -d' ' -f1 | "
1700 " while read MOD ; do echo modinfo:$MOD ; modinfo $MOD ; "
1701 "done"}, CommandOptions::AS_ROOT);
Felipe Lemee4eca582016-06-10 17:48:08 -07001702 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001703
Tom Cherryb87dbfa2020-07-28 11:28:53 -07001704 if (android::base::GetBoolProperty("ro.logd.kernel", false)) {
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001705 DoKernelLogcat();
1706 } else {
1707 do_dmesg();
1708 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001709
Devin Moore8df81bb2022-06-08 22:47:02 +00001710 DumpVintf();
1711
Felipe Lemef0292972016-11-22 13:57:05 -08001712 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001713
Jeff Brown1dc94e32014-09-11 14:15:27 -07001714 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001715 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001716
Jack Yu5a6b2e22020-08-14 18:13:35 +08001717 /* Dump Nfc NCI logs */
1718 ds.AddDir("/data/misc/nfc/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001719
Paul Chang0d2aad72020-02-13 20:04:03 +08001720 if (ds.options_->do_screenshot && !ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001721 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001722 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001723 }
1724
Felipe Lemee184f662016-10-27 10:04:47 -07001725 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001726
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001727 MaybeAddSystemTraceToZip();
1728
Narayan Kamath8f788292017-05-25 13:20:39 +01001729 // NOTE: tombstones are always added as separate entries in the zip archive
1730 // and are not interspersed with the main report.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001731 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
Narayan Kamathbd863722017-06-01 18:50:12 +01001732 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001733 if (!tombstones_dumped) {
1734 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001735 }
1736
Jayachandran Ca94c7172017-06-10 15:08:12 -07001737 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001738
Lorenzo Colitti807f2dd2022-05-27 12:48:37 +09001739 RunDumpsys("EBPF MAP STATS", {"connectivity", "trafficcontroller"});
Chenbo Feng276a3b62018-08-07 11:44:49 -07001740
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001741 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001742
Woody Lin20767a92022-11-29 15:50:24 +08001743 DumpShutdownCheckpoints();
1744
Jayachandran Ca94c7172017-06-10 15:08:12 -07001745 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001746
1747 dump_route_tables();
1748
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001749 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1750 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1751 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001752
Nandana Dutt5c390032019-03-12 10:52:56 +00001753 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysHigh);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001754
Chiachang Wang668ede42021-05-17 17:14:20 +08001755 // The dump mechanism in connectivity is refactored due to modularization work. Connectivity can
1756 // only register with a default priority(NORMAL priority). Dumpstate has to call connectivity
1757 // dump with priority parameters to dump high priority information.
1758 RunDumpsys("SERVICE HIGH connectivity", {"connectivity", "--dump-priority", "HIGH"},
1759 CommandOptions::WithTimeout(10).Build());
1760
Elliott Hughes23ccc622017-02-28 10:14:22 -08001761 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001762
Joe Onoratod38bc3a2023-06-29 15:48:28 -07001763 DumpFile("SYSTEM BUILD-TIME RELEASE FLAGS", "/system/etc/build_flags.json");
1764 DumpFile("SYSTEM_EXT BUILD-TIME RELEASE FLAGS", "/system_ext/etc/build_flags.json");
1765 DumpFile("PRODUCT BUILD-TIME RELEASE FLAGS", "/product/etc/build_flags.json");
1766 DumpFile("VENDOR BUILD-TIME RELEASE FLAGS", "/vendor/etc/build_flags.json");
1767
Mårten Kongstad5ad813f2023-09-28 10:09:18 +02001768 RunCommand("ACONFIG FLAGS", {PRINT_FLAGS},
1769 CommandOptions::WithTimeout(10).Always().DropRoot().Build());
Joe Onoratod38bc3a2023-06-29 15:48:28 -07001770
Jin Qianf334d662017-10-10 14:41:37 -07001771 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001772
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001773 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001774
Colin Crossf45fa6b2012-03-26 12:38:26 -07001775 /* Binder state is expensive to look at as it uses a lot of memory. */
Hridya Valsaraju920ba712020-02-09 16:27:01 -08001776 std::string binder_logs_dir = access("/dev/binderfs/binder_logs", R_OK) ?
1777 "/sys/kernel/debug/binder" : "/dev/binderfs/binder_logs";
1778
1779 DumpFile("BINDER FAILED TRANSACTION LOG", binder_logs_dir + "/failed_transaction_log");
1780 DumpFile("BINDER TRANSACTION LOG", binder_logs_dir + "/transaction_log");
1781 DumpFile("BINDER TRANSACTIONS", binder_logs_dir + "/transactions");
1782 DumpFile("BINDER STATS", binder_logs_dir + "/stats");
1783 DumpFile("BINDER STATE", binder_logs_dir + "/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001784
Yifan Hongd90cc652020-02-08 16:52:02 -08001785 ds.AddDir(SNAPSHOTCTL_LOG_DIR, false);
1786
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001787 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001788 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_board));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001789 } else {
1790 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
1791 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001792
Steven Moreland7440ddb2016-12-15 16:13:39 -08001793 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001794 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1795 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001796 // su does not exist on user builds, so try running without it.
1797 // This way any implementations of vril-dump that do not require
1798 // root can run on user builds.
1799 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001800 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001801 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001802 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001803 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001804 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001805 }
1806
Felipe Lemed8b94e52016-12-08 10:21:44 -08001807 printf("========================================================\n");
1808 printf("== Android Framework Services\n");
1809 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001810
Nandana Dutt5c390032019-03-12 10:52:56 +00001811 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001812
Jack He91ff2fe2021-02-18 18:23:43 -08001813 /* Dump Bluetooth HCI logs after getting bluetooth_manager dumpsys */
1814 ds.AddDir("/data/misc/bluetooth/logs", true);
1815
Rhed Jaoe017f982020-07-21 17:58:41 +08001816 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001817 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_checkins));
Rhed Jaoe017f982020-07-21 17:58:41 +08001818 } else {
1819 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_CHECKINS_TASK, DumpCheckins);
1820 }
Dianne Hackborn02bea972013-06-26 18:59:09 -07001821
Rhed Jaoc5f7ec32020-12-22 22:11:08 +08001822 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpAppInfos);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001823
Adrian Roos8b397ab2017-04-04 16:35:44 -07001824 printf("========================================================\n");
1825 printf("== Dropbox crashes\n");
1826 printf("========================================================\n");
1827
1828 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1829 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1830
Felipe Lemed8b94e52016-12-08 10:21:44 -08001831 printf("========================================================\n");
1832 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1833 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1834 printf("========================================================\n");
1835 printf("== dumpstate: done (id %d)\n", ds.id_);
1836 printf("========================================================\n");
Bookatz38472142018-09-28 10:20:24 -07001837
1838 printf("========================================================\n");
1839 printf("== Obtaining statsd metadata\n");
1840 printf("========================================================\n");
1841 // This differs from the usual dumpsys stats, which is the stats report data.
1842 RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
Mike Ma5c267872019-08-21 11:31:34 -07001843
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +09001844 // Add linker configuration directory
1845 ds.AddDir(LINKERCONFIG_DIR, true);
1846
Li Li830179f2022-01-04 12:53:29 -08001847 /* Dump frozen cgroupfs */
1848 dump_frozen_cgroupfs();
Li Li2eedd412021-06-30 15:11:53 -07001849
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001850 if (ds.dump_pool_) {
Aaron Huang24d215d2022-04-27 18:51:16 +08001851 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_netstats_report));
1852 } else {
1853 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_NETSTATS_PROTO_TASK,
1854 DumpNetstatsProto);
1855 }
1856
1857 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001858 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_incident_report));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001859 } else {
1860 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_INCIDENT_REPORT_TASK,
1861 DumpIncidentReport);
1862 }
Mike Ma5c267872019-08-21 11:31:34 -07001863
Kean Mariotti306633e2022-09-05 16:30:47 +00001864 if (ds.dump_pool_) {
1865 WaitForTask(std::move(post_process_ui_traces));
1866 } else {
1867 RUN_SLOW_FUNCTION_AND_LOG(POST_PROCESS_UI_TRACES_TASK, MaybePostProcessUiTraces);
1868 }
1869
1870 MaybeAddUiTracesToZip();
1871
Nandana Dutt5c390032019-03-12 10:52:56 +00001872 return Dumpstate::RunStatus::OK;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001873}
1874
Nandana Dutt5c390032019-03-12 10:52:56 +00001875/*
1876 * Dumps state for the default case; drops root after it's no longer necessary.
1877 *
1878 * Returns RunStatus::OK if everything went fine.
1879 * Returns RunStatus::ERROR if there was an error.
1880 * Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport
1881 * with the caller.
1882 */
Jichao Lie89d9c12019-11-21 19:02:51 -08001883Dumpstate::RunStatus Dumpstate::DumpstateDefaultAfterCritical() {
Nandana Duttdb379fa2019-10-09 16:54:41 +01001884 // Capture first logcat early on; useful to take a snapshot before dumpstate logs take over the
1885 // buffer.
1886 DoLogcat();
1887 // Capture timestamp after first logcat to use in next logcat
1888 time_t logcat_ts = time(nullptr);
1889
Nandana Dutt4be45d12018-09-26 15:04:23 +01001890 /* collect stack traces from Dalvik and native processes (needs root) */
Chris Morinbc223142022-02-04 14:17:11 -08001891 std::future<std::string> dump_traces;
Rhed Jao5377d792020-07-16 17:37:39 +08001892 if (dump_pool_) {
1893 RETURN_IF_USER_DENIED_CONSENT();
1894 // One thread is enough since we only need to enqueue DumpTraces here.
1895 dump_pool_->start(/* thread_counts = */1);
1896
1897 // DumpTraces takes long time, post it to the another thread in the
1898 // pool, if pool is available
Chris Morinbc223142022-02-04 14:17:11 -08001899 dump_traces = dump_pool_->enqueueTask(
1900 DUMP_TRACES_TASK, &Dumpstate::DumpTraces, &ds, &dump_traces_path);
Rhed Jao5377d792020-07-16 17:37:39 +08001901 } else {
1902 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_TRACES_TASK, ds.DumpTraces,
1903 &dump_traces_path);
1904 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001905
1906 /* Run some operations that require root. */
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001907 if (!PropertiesHelper::IsDryRun()) {
Chris Morinc2cba7a2022-02-01 17:06:50 -08001908 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX);
1909 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX);
Woody Lin20767a92022-11-29 15:50:24 +08001910 ds.shutdown_checkpoints_ = GetDumpFds(
1911 SHUTDOWN_CHECKPOINTS_DIR, SHUTDOWN_CHECKPOINTS_FILE_PREFIX);
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001912 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001913
1914 ds.AddDir(RECOVERY_DIR, true);
1915 ds.AddDir(RECOVERY_DATA_DIR, true);
1916 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
Kelvin Zhang6eaa0f92022-09-12 09:29:19 -07001917 ds.AddDir(UPDATE_ENGINE_PREF_DIR, true);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001918 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1919 if (!PropertiesHelper::IsUserBuild()) {
1920 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1921 ds.AddDir(PROFILE_DATA_DIR_REF, true);
Calin Juravlef84d3692020-04-28 15:31:12 -07001922 ds.AddZipEntry(ZIP_ROOT_DIR + PACKAGE_DEX_USE_LIST, PACKAGE_DEX_USE_LIST);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001923 }
Jerry Changa1df8a92020-01-02 16:03:39 +08001924 ds.AddDir(PREREBOOT_DATA_DIR, false);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001925 add_mountinfo();
Peter Collingbourne78aa2942023-02-15 14:50:31 -08001926 for (const char* path : {"/proc/cpuinfo", "/proc/meminfo"}) {
1927 ds.AddZipEntry(ZIP_ROOT_DIR + path, path);
1928 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001929 DumpIpTablesAsRoot();
David Andersond9ba4752018-12-11 18:26:59 -08001930 DumpDynamicPartitionInfo();
Yifan Hong3945e1b2019-10-29 12:59:23 -07001931 ds.AddDir(OTA_METADATA_DIR, true);
Jeff Sharkey9df29d52023-02-06 14:26:30 -07001932 if (!PropertiesHelper::IsUserBuild()) {
1933 // Include dropbox entry files inside ZIP, but exclude
1934 // noisy WTF and StrictMode entries
1935 dump_files("", DROPBOX_DIR, skip_wtf_strictmode, _add_file_from_fd);
1936 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001937
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001938 // Capture any IPSec policies in play. No keys are exposed here.
Nandana Dutt4be45d12018-09-26 15:04:23 +01001939 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1940
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001941 // Dump IPsec stats. No keys are exposed here.
1942 DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
1943
Nandana Dutt4be45d12018-09-26 15:04:23 +01001944 // Run ss as root so we can see socket marks.
1945 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1946
1947 // Run iotop as root to show top 100 IO threads
1948 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1949
Erick Reyese68df822019-02-11 14:46:36 -08001950 // Gather shared memory buffer info if the product implements it
Hridya Valsaraju1da80c52021-01-09 22:10:11 -08001951 RunCommand("Dmabuf dump", {"dmabuf_dump"});
1952 RunCommand("Dmabuf per-buffer/per-exporter/per-device stats", {"dmabuf_dump", "-b"});
Erick Reyese68df822019-02-11 14:46:36 -08001953
Minchan Kim22c6a1e2019-09-30 15:58:10 -07001954 DumpFile("PSI cpu", "/proc/pressure/cpu");
1955 DumpFile("PSI memory", "/proc/pressure/memory");
1956 DumpFile("PSI io", "/proc/pressure/io");
1957
Mårten Kongstad60195a72022-09-20 14:14:20 +02001958 RunCommand("SDK EXTENSIONS", {SDK_EXT_INFO, "--dump"},
1959 CommandOptions::WithTimeout(10).Always().DropRoot().Build());
1960
Rhed Jao5377d792020-07-16 17:37:39 +08001961 if (dump_pool_) {
1962 RETURN_IF_USER_DENIED_CONSENT();
Chris Morinbc223142022-02-04 14:17:11 -08001963 WaitForTask(std::move(dump_traces));
Rhed Jao5377d792020-07-16 17:37:39 +08001964
Chris Morinbc223142022-02-04 14:17:11 -08001965 // Current running thread in the pool is the root user also. Delete
1966 // the pool and make a new one later to ensure none of threads in the pool are root.
1967 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao5377d792020-07-16 17:37:39 +08001968 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001969 if (!DropRootUser()) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001970 return Dumpstate::RunStatus::ERROR;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001971 }
1972
Nandana Dutt5c390032019-03-12 10:52:56 +00001973 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttdb379fa2019-10-09 16:54:41 +01001974 Dumpstate::RunStatus status = dumpstate();
1975 // Capture logcat since the last time we did it.
1976 DoSystemLogcat(logcat_ts);
1977 return status;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001978}
1979
Rhed Jaob5685b32020-08-14 17:19:17 +08001980// Common states for telephony and wifi which are needed to be collected before
1981// dumpstate drop the root user.
1982static void DumpstateRadioAsRoot() {
1983 DumpIpTablesAsRoot();
1984 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1985}
1986
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001987// This method collects common dumpsys for telephony and wifi. Typically, wifi
1988// reports are fine to include all information, but telephony reports on user
1989// builds need to strip some content (see DumpstateTelephonyOnly).
1990static void DumpstateRadioCommon(bool include_sensitive_info = true) {
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001991 // We need to be picky about some stuff for telephony reports on user builds.
1992 if (!include_sensitive_info) {
1993 // Only dump the radio log buffer (other buffers and dumps contain too much unrelated info).
1994 DoRadioLogcat();
1995 } else {
Rhed Jaob5685b32020-08-14 17:19:17 +08001996 // DumpHals takes long time, post it to the another thread in the pool,
1997 // if pool is available.
Chris Morinbc223142022-02-04 14:17:11 -08001998 std::future<std::string> dump_hals;
Rhed Jaob5685b32020-08-14 17:19:17 +08001999 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002000 dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
Rhed Jaob5685b32020-08-14 17:19:17 +08002001 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002002 // Contains various system properties and process startup info.
2003 do_dmesg();
2004 // Logs other than the radio buffer may contain package/component names and potential PII.
2005 DoLogcat();
2006 // Too broad for connectivity problems.
2007 DoKmsg();
Rhed Jaob5685b32020-08-14 17:19:17 +08002008 // DumpHals contains unrelated hardware info (camera, NFC, biometrics, ...).
2009 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002010 WaitForTask(std::move(dump_hals));
Rhed Jaob5685b32020-08-14 17:19:17 +08002011 } else {
2012 RUN_SLOW_FUNCTION_AND_LOG(DUMP_HALS_TASK, DumpHals);
2013 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002014 }
2015
Jayachandran Ca94c7172017-06-10 15:08:12 -07002016 DumpPacketStats();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002017 DumpIpAddrAndRules();
2018 dump_route_tables();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002019 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
2020 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08002021}
2022
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002023// We use "telephony" here for legacy reasons, though this now really means "connectivity" (cellular
2024// + wifi + networking). This method collects dumpsys for connectivity debugging only. General rules
2025// for what can be included on user builds: all reported information MUST directly relate to
2026// connectivity debugging or customer support and MUST NOT contain unrelated personally identifiable
2027// information. This information MUST NOT identify user-installed packages (UIDs are OK, package
2028// names are not), and MUST NOT contain logs of user application traffic.
2029// TODO(b/148168577) rename this and other related fields/methods to "connectivity" instead.
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08002030static void DumpstateTelephonyOnly(const std::string& calling_package) {
mukesh agrawal253dad42018-01-23 21:59:59 -08002031 DurationReporter duration_reporter("DUMPSTATE");
Jichao Lie89d9c12019-11-21 19:02:51 -08002032
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002033 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
mukesh agrawal253dad42018-01-23 21:59:59 -08002034
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002035 const bool include_sensitive_info = !PropertiesHelper::IsUserBuild();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002036
Rhed Jaob5685b32020-08-14 17:19:17 +08002037 DumpstateRadioAsRoot();
2038 if (!DropRootUser()) {
2039 return;
2040 }
2041
2042 // Starts thread pool after the root user is dropped, and two additional threads
2043 // are created for DumpHals in the DumpstateRadioCommon and DumpstateBoard.
Chris Morinbc223142022-02-04 14:17:11 -08002044 std::future<std::string> dump_board;
Rhed Jaob5685b32020-08-14 17:19:17 +08002045 if (ds.dump_pool_) {
2046 ds.dump_pool_->start(/*thread_counts =*/2);
2047
2048 // DumpstateBoard takes long time, post it to the another thread in the pool,
2049 // if pool is available.
Chris Morinbc223142022-02-04 14:17:11 -08002050 dump_board = ds.dump_pool_->enqueueTaskWithFd(
2051 DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
Rhed Jaob5685b32020-08-14 17:19:17 +08002052 }
2053
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002054 DumpstateRadioCommon(include_sensitive_info);
2055
2056 if (include_sensitive_info) {
2057 // Contains too much unrelated PII, and given the unstructured nature of sysprops, we can't
2058 // really cherrypick all of the connectivity-related ones. Apps generally have no business
2059 // reading these anyway, and there should be APIs to supply the info in a more app-friendly
2060 // way.
2061 RunCommand("SYSTEM PROPERTIES", {"getprop"});
2062 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002063
2064 printf("========================================================\n");
2065 printf("== Android Framework Services\n");
2066 printf("========================================================\n");
2067
Vishnu Nair652cc802017-11-30 15:18:30 -08002068 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2069 SEC_TO_MSEC(10));
Hunter Knepshield31cbae12021-05-11 16:23:24 -07002070 RunDumpsys("DUMPSYS", {"vcn_management"}, CommandOptions::WithTimeout(90).Build(),
2071 SEC_TO_MSEC(10));
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08002072 if (include_sensitive_info) {
2073 // Carrier apps' services will be dumped below in dumpsys activity service all-non-platform.
2074 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
2075 SEC_TO_MSEC(10));
2076 } else {
2077 // If the caller is a carrier app and has a carrier service, dump it here since we aren't
2078 // running dumpsys activity service all-non-platform below. Due to the increased output, we
2079 // give a higher timeout as well.
2080 RunDumpsys("DUMPSYS", {"carrier_config", "--requesting-package", calling_package},
2081 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(30));
2082 }
2083 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002084 RunDumpsys("DUMPSYS", {"netpolicy"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2085 RunDumpsys("DUMPSYS", {"network_management"}, CommandOptions::WithTimeout(90).Build(),
Sooraj Sasindrane8d98912018-04-20 11:31:55 -07002086 SEC_TO_MSEC(10));
Hunter Knepshield0fe51b12020-03-05 16:58:20 -08002087 RunDumpsys("DUMPSYS", {"telephony.registry"}, CommandOptions::WithTimeout(90).Build(),
2088 SEC_TO_MSEC(10));
Jack Yu773cc032023-03-16 22:43:39 -07002089 RunDumpsys("DUMPSYS", {"isub"}, CommandOptions::WithTimeout(90).Build(),
2090 SEC_TO_MSEC(10));
Grant Menke56698972023-02-24 13:11:07 -08002091 RunDumpsys("DUMPSYS", {"telecom"}, CommandOptions::WithTimeout(90).Build(),
2092 SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002093 if (include_sensitive_info) {
2094 // Contains raw IP addresses, omit from reports on user builds.
2095 RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2096 // Contains raw destination IP/MAC addresses, omit from reports on user builds.
2097 RunDumpsys("DUMPSYS", {"connmetrics"}, CommandOptions::WithTimeout(90).Build(),
2098 SEC_TO_MSEC(10));
2099 // Contains package/component names, omit from reports on user builds.
2100 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
2101 SEC_TO_MSEC(10));
2102 // Contains package names, but should be relatively simple to remove them (also contains
2103 // UIDs already), omit from reports on user builds.
2104 RunDumpsys("BATTERYSTATS", {"deviceidle"}, CommandOptions::WithTimeout(90).Build(),
2105 SEC_TO_MSEC(10));
2106 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002107
2108 printf("========================================================\n");
2109 printf("== Running Application Services\n");
2110 printf("========================================================\n");
2111
2112 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
2113
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002114 if (include_sensitive_info) {
2115 printf("========================================================\n");
2116 printf("== Running Application Services (non-platform)\n");
2117 printf("========================================================\n");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002118
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002119 // Contains package/component names and potential PII, omit from reports on user builds.
2120 // To get dumps of the active CarrierService(s) on user builds, we supply an argument to the
2121 // carrier_config dumpsys instead.
2122 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
2123 DUMPSYS_COMPONENTS_OPTIONS);
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002124
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002125 printf("========================================================\n");
2126 printf("== Checkins\n");
2127 printf("========================================================\n");
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002128
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002129 // Contains package/component names, omit from reports on user builds.
2130 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
2131 }
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002132
2133 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07002134 printf("== dumpstate: done (id %d)\n", ds.id_);
2135 printf("========================================================\n");
Rhed Jaob5685b32020-08-14 17:19:17 +08002136
2137 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002138 WaitForTask(std::move(dump_board));
Rhed Jaob5685b32020-08-14 17:19:17 +08002139 } else {
2140 RUN_SLOW_FUNCTION_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
2141 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002142}
2143
mukesh agrawal253dad42018-01-23 21:59:59 -08002144// This method collects dumpsys for wifi debugging only
2145static void DumpstateWifiOnly() {
2146 DurationReporter duration_reporter("DUMPSTATE");
2147
Rhed Jaob5685b32020-08-14 17:19:17 +08002148 DumpstateRadioAsRoot();
2149 if (!DropRootUser()) {
2150 return;
2151 }
2152
2153 // Starts thread pool after the root user is dropped. Only one additional
2154 // thread is needed for DumpHals in the DumpstateRadioCommon.
2155 if (ds.dump_pool_) {
2156 ds.dump_pool_->start(/*thread_counts =*/1);
2157 }
2158
mukesh agrawal253dad42018-01-23 21:59:59 -08002159 DumpstateRadioCommon();
2160
2161 printf("========================================================\n");
2162 printf("== Android Framework Services\n");
2163 printf("========================================================\n");
2164
2165 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2166 SEC_TO_MSEC(10));
2167 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
2168 SEC_TO_MSEC(10));
2169
2170 printf("========================================================\n");
2171 printf("== dumpstate: done (id %d)\n", ds.id_);
2172 printf("========================================================\n");
2173}
2174
Elis Elliott8e401ad2023-08-08 11:18:59 +00002175// Collects a lightweight dumpstate to be used for debugging onboarding related flows.
2176static void DumpstateOnboardingOnly() {
2177 ds.AddDir(LOGPERSIST_DATA_DIR, false);
2178}
2179
Nandana Duttcf419a72019-03-14 10:40:17 +00002180Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
Gavin Corkery789d7a52021-02-24 23:52:35 +00002181 const std::string temp_file_pattern = ds.bugreport_internal_dir_ + "/dumptrace_XXXXXX";
Nandana Duttfaafd522019-03-11 09:23:09 +00002182 const size_t buf_size = temp_file_pattern.length() + 1;
2183 std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
2184 memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
2185
2186 // Create a new, empty file to receive all trace dumps.
2187 //
2188 // TODO: This can be simplified once we remove support for the old style
2189 // dumps. We can have a file descriptor passed in to dump_traces instead
2190 // of creating a file, closing it and then reopening it again.
2191 android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
2192 if (fd < 0) {
2193 MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002194 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002195 }
2196
2197 // Nobody should have access to this temporary file except dumpstate, but we
2198 // temporarily grant 'read' to 'others' here because this file is created
2199 // when tombstoned is still running as root, but dumped after dropping. This
2200 // can go away once support for old style dumping has.
2201 const int chmod_ret = fchmod(fd, 0666);
2202 if (chmod_ret < 0) {
2203 MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002204 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002205 }
2206
2207 std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
2208 if (proc.get() == nullptr) {
2209 MYLOGE("opendir /proc failed: %s\n", strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002210 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002211 }
2212
2213 // Number of times process dumping has timed out. If we encounter too many
2214 // failures, we'll give up.
2215 int timeout_failures = 0;
2216 bool dalvik_found = false;
2217
Jayant Chowdharya0a8eb22022-05-20 03:30:09 +00002218 const std::set<int> hal_pids = get_interesting_pids();
Nandana Duttfaafd522019-03-11 09:23:09 +00002219
2220 struct dirent* d;
2221 while ((d = readdir(proc.get()))) {
Nandana Duttcf419a72019-03-14 10:40:17 +00002222 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttfaafd522019-03-11 09:23:09 +00002223 int pid = atoi(d->d_name);
2224 if (pid <= 0) {
2225 continue;
2226 }
2227
Kevin Jeond0f8a982023-04-07 14:27:11 -04002228 // Skip cached processes.
2229 if (IsCached(pid)) {
2230 // For consistency, the header and footer to this message match those
2231 // dumped by debuggerd in the success case.
2232 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
2233 dprintf(fd, "Dump skipped for cached process.\n");
2234 dprintf(fd, "---- end %d ----", pid);
2235 continue;
2236 }
2237
Nandana Duttfaafd522019-03-11 09:23:09 +00002238 const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
2239 std::string exe;
2240 if (!android::base::Readlink(link_name, &exe)) {
2241 continue;
2242 }
2243
2244 bool is_java_process;
2245 if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
2246 // Don't bother dumping backtraces for the zygote.
2247 if (IsZygote(pid)) {
2248 continue;
2249 }
2250
2251 dalvik_found = true;
2252 is_java_process = true;
2253 } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
2254 is_java_process = false;
2255 } else {
2256 // Probably a native process we don't care about, continue.
2257 continue;
2258 }
2259
2260 // If 3 backtrace dumps fail in a row, consider debuggerd dead.
2261 if (timeout_failures == 3) {
2262 dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
2263 break;
2264 }
2265
2266 const uint64_t start = Nanotime();
2267 const int ret = dump_backtrace_to_file_timeout(
Kevin Jeonb8a39362023-04-04 15:00:34 -04002268 pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace, 3, fd);
Nandana Duttfaafd522019-03-11 09:23:09 +00002269
2270 if (ret == -1) {
2271 // For consistency, the header and footer to this message match those
2272 // dumped by debuggerd in the success case.
2273 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
2274 dprintf(fd, "Dump failed, likely due to a timeout.\n");
2275 dprintf(fd, "---- end %d ----", pid);
2276 timeout_failures++;
2277 continue;
2278 }
2279
2280 // We've successfully dumped stack traces, reset the failure count
2281 // and write a summary of the elapsed time to the file and continue with the
2282 // next process.
2283 timeout_failures = 0;
2284
2285 dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
2286 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
2287 }
2288
2289 if (!dalvik_found) {
2290 MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
2291 }
2292
Nandana Duttcf419a72019-03-14 10:40:17 +00002293 *path = file_name_buf.release();
2294 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002295}
2296
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002297static dumpstate_hal_hidl::DumpstateMode GetDumpstateHalModeHidl(
2298 const Dumpstate::BugreportMode bugreport_mode) {
2299 switch (bugreport_mode) {
2300 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2301 return dumpstate_hal_hidl::DumpstateMode::FULL;
2302 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2303 return dumpstate_hal_hidl::DumpstateMode::INTERACTIVE;
2304 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2305 return dumpstate_hal_hidl::DumpstateMode::REMOTE;
2306 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2307 return dumpstate_hal_hidl::DumpstateMode::WEAR;
2308 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2309 return dumpstate_hal_hidl::DumpstateMode::CONNECTIVITY;
2310 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2311 return dumpstate_hal_hidl::DumpstateMode::WIFI;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002312 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002313 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2314 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2315 }
2316 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2317}
2318
2319static dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode GetDumpstateHalModeAidl(
2320 const Dumpstate::BugreportMode bugreport_mode) {
2321 switch (bugreport_mode) {
2322 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2323 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::FULL;
2324 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2325 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::INTERACTIVE;
2326 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2327 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::REMOTE;
2328 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2329 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WEAR;
2330 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2331 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::CONNECTIVITY;
2332 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2333 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WIFI;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002334 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002335 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2336 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2337 }
2338 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2339}
2340
2341static void DoDumpstateBoardHidl(
2342 const sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_1_0,
2343 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2344 const Dumpstate::BugreportMode bugreport_mode,
2345 const size_t timeout_sec) {
2346
2347 using ScopedNativeHandle =
2348 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
2349 ScopedNativeHandle handle(native_handle_create(static_cast<int>(dumpstate_fds.size()), 0),
2350 [](native_handle_t* handle) {
2351 // we don't close file handle's here
2352 // via native_handle_close(handle)
2353 // instead we let dumpstate_fds close the file handles when
2354 // dumpstate_fds gets destroyed
2355 native_handle_delete(handle);
2356 });
2357 if (handle == nullptr) {
2358 MYLOGE("Could not create native_handle for dumpstate HAL\n");
2359 return;
2360 }
2361
2362 for (size_t i = 0; i < dumpstate_fds.size(); i++) {
2363 handle.get()->data[i] = dumpstate_fds[i].get();
2364 }
2365
2366 // Prefer version 1.1 if available. New devices launching with R are no longer allowed to
2367 // implement just 1.0.
2368 const char* descriptor_to_kill;
2369 using DumpstateBoardTask = std::packaged_task<bool()>;
2370 DumpstateBoardTask dumpstate_board_task;
2371 sp<dumpstate_hal_hidl::IDumpstateDevice> dumpstate_hal(
2372 dumpstate_hal_hidl::IDumpstateDevice::castFrom(dumpstate_hal_1_0));
2373 if (dumpstate_hal != nullptr) {
2374 MYLOGI("Using IDumpstateDevice v1.1 HIDL HAL");
2375
2376 dumpstate_hal_hidl::DumpstateMode dumpstate_hal_mode =
2377 GetDumpstateHalModeHidl(bugreport_mode);
2378
2379 descriptor_to_kill = dumpstate_hal_hidl::IDumpstateDevice::descriptor;
2380 dumpstate_board_task =
2381 DumpstateBoardTask([timeout_sec, dumpstate_hal_mode, dumpstate_hal, &handle]() -> bool {
2382 ::android::hardware::Return<dumpstate_hal_hidl::DumpstateStatus> status =
2383 dumpstate_hal->dumpstateBoard_1_1(handle.get(), dumpstate_hal_mode,
2384 SEC_TO_MSEC(timeout_sec));
2385 if (!status.isOk()) {
2386 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2387 return false;
2388 } else if (status != dumpstate_hal_hidl::DumpstateStatus::OK) {
2389 MYLOGE("dumpstateBoard failed with DumpstateStatus::%s\n",
2390 dumpstate_hal_hidl::toString(status).c_str());
2391 return false;
2392 }
2393 return true;
2394 });
2395 } else {
2396 MYLOGI("Using IDumpstateDevice v1.0 HIDL HAL");
2397
2398 descriptor_to_kill = dumpstate_hal_hidl_1_0::IDumpstateDevice::descriptor;
2399 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal_1_0, &handle]() -> bool {
2400 ::android::hardware::Return<void> status =
2401 dumpstate_hal_1_0->dumpstateBoard(handle.get());
2402 if (!status.isOk()) {
2403 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2404 return false;
2405 }
2406 return true;
2407 });
2408 }
2409 auto result = dumpstate_board_task.get_future();
2410 std::thread(std::move(dumpstate_board_task)).detach();
2411
2412 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2413 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2414 if (!android::base::SetProperty(
2415 "ctl.interface_restart",
2416 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2417 MYLOGE("Couldn't restart dumpstate HAL\n");
2418 }
2419 }
2420 // Wait some time for init to kill dumpstate vendor HAL
2421 constexpr size_t killing_timeout_sec = 10;
2422 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2423 MYLOGE(
2424 "killing dumpstateBoard timed out after %zus, continue and "
2425 "there might be racing in content\n",
2426 killing_timeout_sec);
2427 }
2428}
2429
2430static void DoDumpstateBoardAidl(
2431 const std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal,
2432 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2433 const Dumpstate::BugreportMode bugreport_mode, const size_t timeout_sec) {
2434 MYLOGI("Using IDumpstateDevice AIDL HAL");
2435
2436 const char* descriptor_to_kill;
2437 using DumpstateBoardTask = std::packaged_task<bool()>;
2438 DumpstateBoardTask dumpstate_board_task;
2439 dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode dumpstate_hal_mode =
2440 GetDumpstateHalModeAidl(bugreport_mode);
2441
2442 descriptor_to_kill = dumpstate_hal_aidl::IDumpstateDevice::descriptor;
2443 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal, &dumpstate_fds, dumpstate_hal_mode,
2444 timeout_sec]() -> bool {
2445 auto status = dumpstate_hal->dumpstateBoard(dumpstate_fds, dumpstate_hal_mode, timeout_sec);
2446
2447 if (!status.isOk()) {
2448 MYLOGE("dumpstateBoard failed: %s\n", status.getDescription().c_str());
2449 return false;
2450 }
2451 return true;
2452 });
2453 auto result = dumpstate_board_task.get_future();
2454 std::thread(std::move(dumpstate_board_task)).detach();
2455
2456 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2457 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2458 if (!android::base::SetProperty(
2459 "ctl.interface_restart",
2460 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2461 MYLOGE("Couldn't restart dumpstate HAL\n");
2462 }
2463 }
2464 // Wait some time for init to kill dumpstate vendor HAL
2465 constexpr size_t killing_timeout_sec = 10;
2466 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2467 MYLOGE(
2468 "killing dumpstateBoard timed out after %zus, continue and "
2469 "there might be racing in content\n",
2470 killing_timeout_sec);
2471 }
2472}
2473
2474static std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> GetDumpstateBoardAidlService() {
2475 const std::string aidl_instance_name =
2476 std::string(dumpstate_hal_aidl::IDumpstateDevice::descriptor) + "/default";
2477
2478 if (!AServiceManager_isDeclared(aidl_instance_name.c_str())) {
2479 return nullptr;
2480 }
2481
2482 ndk::SpAIBinder dumpstateBinder(AServiceManager_waitForService(aidl_instance_name.c_str()));
2483
2484 return dumpstate_hal_aidl::IDumpstateDevice::fromBinder(dumpstateBinder);
2485}
2486
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002487void Dumpstate::DumpstateBoard(int out_fd) {
2488 dprintf(out_fd, "========================================================\n");
2489 dprintf(out_fd, "== Board\n");
2490 dprintf(out_fd, "========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08002491
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002492 /*
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002493 * mount debugfs for non-user builds with ro.product.debugfs_restrictions.enabled
Hridya Valsaraju51101602021-04-02 14:32:46 -07002494 * set to true and unmount it after invoking dumpstateBoard_* methods.
2495 * This is to enable debug builds to not have debugfs mounted during runtime.
2496 * It will also ensure that debugfs is only accessed by the dumpstate HAL.
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002497 */
Hridya Valsaraju51101602021-04-02 14:32:46 -07002498 auto mount_debugfs =
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002499 android::base::GetBoolProperty("ro.product.debugfs_restrictions.enabled", false);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002500 if (mount_debugfs) {
2501 RunCommand("mount debugfs", {"mount", "-t", "debugfs", "debugfs", "/sys/kernel/debug"},
2502 AS_ROOT_20);
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002503 RunCommand("chmod debugfs", {"chmod", "0755", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002504 }
2505
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002506 std::vector<std::string> paths;
2507 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07002508 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002509 paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
2510 kDumpstateBoardFiles[i].c_str()));
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002511 remover.emplace_back(android::base::make_scope_guard(
2512 std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002513 }
Jie Song9fbfad02017-06-20 16:29:42 -07002514
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002515 // get dumpstate HAL AIDL implementation
2516 std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal_handle_aidl(
2517 GetDumpstateBoardAidlService());
2518 if (dumpstate_hal_handle_aidl == nullptr) {
2519 MYLOGI("No IDumpstateDevice AIDL implementation\n");
2520 }
2521
2522 // get dumpstate HAL HIDL implementation, only if AIDL HAL implementation not found
2523 sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_handle_hidl_1_0 = nullptr;
2524 if (dumpstate_hal_handle_aidl == nullptr) {
2525 dumpstate_hal_handle_hidl_1_0 = dumpstate_hal_hidl_1_0::IDumpstateDevice::getService();
2526 if (dumpstate_hal_handle_hidl_1_0 == nullptr) {
2527 MYLOGI("No IDumpstateDevice HIDL implementation\n");
2528 }
2529 }
2530
2531 // if neither HIDL nor AIDL implementation found, then return
2532 if (dumpstate_hal_handle_hidl_1_0 == nullptr && dumpstate_hal_handle_aidl == nullptr) {
2533 MYLOGE("Could not find IDumpstateDevice implementation\n");
Wei Wang587eac92018-04-05 12:17:20 -07002534 return;
2535 }
2536
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002537 // this is used to hold the file descriptors and when this variable goes out of scope
2538 // the file descriptors are closed
2539 std::vector<::ndk::ScopedFileDescriptor> dumpstate_fds;
Wei Wang587eac92018-04-05 12:17:20 -07002540
Nandana Dutt5c390032019-03-12 10:52:56 +00002541 // TODO(128270426): Check for consent in between?
Wei Wang587eac92018-04-05 12:17:20 -07002542 for (size_t i = 0; i < paths.size(); i++) {
2543 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
2544
2545 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
2546 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
2547 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
2548 if (fd < 0) {
2549 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
2550 return;
2551 }
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002552
2553 dumpstate_fds.emplace_back(fd.release());
2554 // we call fd.release() here to make sure "fd" does not get closed
2555 // after "fd" goes out of scope after this block.
2556 // "fd" will be closed when "dumpstate_fds" goes out of scope
2557 // i.e. when we exit this function
Wei Wang587eac92018-04-05 12:17:20 -07002558 }
2559
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002560 // Given that bugreport is required to diagnose failures, it's better to set an arbitrary amount
2561 // of timeout for IDumpstateDevice than to block the rest of bugreport. In the timeout case, we
2562 // will kill the HAL and grab whatever it dumped in time.
Michael Eastwood8523ea02022-03-10 16:33:08 -08002563 constexpr size_t timeout_sec = 45;
Wei Wang587eac92018-04-05 12:17:20 -07002564
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002565 if (dumpstate_hal_handle_aidl != nullptr) {
2566 DoDumpstateBoardAidl(dumpstate_hal_handle_aidl, dumpstate_fds, options_->bugreport_mode,
2567 timeout_sec);
2568 } else if (dumpstate_hal_handle_hidl_1_0 != nullptr) {
2569 // run HIDL HAL only if AIDL HAL not found
2570 DoDumpstateBoardHidl(dumpstate_hal_handle_hidl_1_0, dumpstate_fds, options_->bugreport_mode,
2571 timeout_sec);
Wei Wang587eac92018-04-05 12:17:20 -07002572 }
2573
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002574 if (mount_debugfs) {
Hridya Valsaraju51101602021-04-02 14:32:46 -07002575 auto keep_debugfs_mounted =
2576 android::base::GetProperty("persist.dbg.keep_debugfs_mounted", "");
2577 if (keep_debugfs_mounted.empty())
2578 RunCommand("unmount debugfs", {"umount", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002579 }
2580
Wei Wang587eac92018-04-05 12:17:20 -07002581 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
2582 for (size_t i = 0; i < paths.size(); i++) {
2583 struct stat s;
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002584 if (fstat(dumpstate_fds[i].get(), &s) == -1) {
2585 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(), strerror(errno));
Wei Wang587eac92018-04-05 12:17:20 -07002586 file_sizes[i] = -1;
2587 continue;
2588 }
2589 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002590 }
2591
2592 for (size_t i = 0; i < paths.size(); i++) {
2593 if (file_sizes[i] == -1) {
2594 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002595 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002596 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07002597 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002598 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002599 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002600 remover[i].Disable();
2601 EnqueueAddZipEntryAndCleanupIfNeeded(kDumpstateBoardFiles[i], paths[i]);
2602 dprintf(out_fd, "*** See %s entry ***\n", kDumpstateBoardFiles[i].c_str());
Jie Song9fbfad02017-06-20 16:29:42 -07002603 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08002604}
2605
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002606static void ShowUsage() {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002607 fprintf(stderr,
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002608 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o directory] [-p] "
2609 "[-s] [-S] [-q] [-P] [-R] [-L] [-V version]\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002610 " -h: display this help message\n"
2611 " -b: play sound file instead of vibrate, at beginning of job\n"
2612 " -e: play sound file instead of vibrate, at end of job\n"
mhasank2d75c442020-06-11 15:05:25 -07002613 " -o: write to custom directory (only in limited mode)\n"
Abhijeet Kaurbb55a3b2019-06-13 18:07:25 +01002614 " -p: capture screenshot to filename.png\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002615 " -s: write zipped file to control socket (for init)\n"
2616 " -S: write file location to control socket (for init)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002617 " -q: disable vibrate\n"
Abhijeet Kaure370d682019-10-01 16:49:30 +01002618 " -P: send broadcast when started and do progress updates\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002619 " -R: take bugreport in remote mode (shouldn't be used with -P)\n"
Nandana Dutt235864b2019-01-22 12:10:16 +00002620 " -w: start binder service and make it wait for a call to startBugreport\n"
mhasankd451a472020-05-26 18:02:39 -07002621 " -L: output limited information that is safe for submission in feedback reports\n"
Felipe Lemed071c682016-10-20 16:48:00 -07002622 " -v: prints the dumpstate header and exit\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002623}
2624
Wei Liuf87959e2016-08-26 14:51:42 -07002625static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07002626 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07002627}
2628
Felipe Leme1d486fe2016-10-14 18:06:47 -07002629bool Dumpstate::FinishZipFile() {
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002630 // Runs all enqueued adding zip entry and cleanup tasks before finishing the zip file.
2631 if (zip_entry_tasks_) {
2632 zip_entry_tasks_->run(/* do_cancel = */false);
2633 }
2634
Felipe Leme9a523ae2016-10-20 15:10:33 -07002635 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07002636 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07002637 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002638 // Final timestamp
2639 char date[80];
2640 time_t the_real_now_please_stand_up = time(nullptr);
2641 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002642 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002643 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002644
Felipe Leme9a523ae2016-10-20 15:10:33 -07002645 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002646 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08002647 return false;
2648 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07002649 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002650 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08002651 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08002652 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08002653
Felipe Leme0f3fb202016-06-10 17:10:53 -07002654 // Add log file (which contains stderr output) to zip...
2655 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002656 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07002657 MYLOGE("Failed to add dumpstate log to .zip file\n");
2658 return false;
2659 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002660 // TODO: Should truncate the existing file.
2661 // ... and re-open it for further logging.
Nandana Dutta344cb62019-02-22 15:12:35 +00002662 if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
2663 return false;
2664 }
Felipe Leme0f3fb202016-06-10 17:10:53 -07002665 fprintf(stderr, "\n");
2666
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002667 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07002668 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002669 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002670 return false;
2671 }
2672
Felipe Leme1d486fe2016-10-14 18:06:47 -07002673 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
2674 ds.zip_file.reset(nullptr);
2675
Felipe Lemee9d2c542016-11-15 11:48:26 -08002676 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002677 android::os::UnlinkAndLogOnError(tmp_path_);
Felipe Lemec4eee562016-04-21 15:42:55 -07002678
Felipe Leme1e9edc62015-12-21 16:02:13 -08002679 return true;
2680}
Felipe Leme6e01fa62015-11-11 19:35:14 -08002681
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00002682static void SendBroadcast(const std::string& action,
2683 const std::vector<std::string>& args,
2684 int32_t user_id) {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002685 // clang-format off
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00002686 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user",
2687 std::to_string(user_id), "--receiver-foreground",
2688 "--receiver-include-background", "-a", action};
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002689 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08002690
2691 am.insert(am.end(), args.begin(), args.end());
2692
Felipe Leme8d2410e2017-02-08 09:46:08 -08002693 RunCommand("", am,
2694 CommandOptions::WithTimeout(20)
2695 .Log("Sending broadcast: '%s'\n")
2696 .Always()
2697 .DropRoot()
2698 .RedirectStderr()
2699 .Build());
2700}
2701
Felipe Leme35b8cf12017-02-10 15:47:29 -08002702static void Vibrate(int duration_ms) {
2703 // clang-format off
Lais Andrade51156962021-02-22 19:21:35 +00002704 std::vector<std::string> args = {"cmd", "vibrator_manager", "synced", "-f", "-d", "dumpstate",
2705 "oneshot", std::to_string(duration_ms)};
2706 RunCommand("", args,
Felipe Leme35b8cf12017-02-10 15:47:29 -08002707 CommandOptions::WithTimeout(10)
2708 .Log("Vibrate: '%s'\n")
2709 .Always()
2710 .Build());
2711 // clang-format on
2712}
2713
Nandana Dutt979388e2018-11-30 16:48:55 +00002714static void MaybeResolveSymlink(std::string* path) {
2715 std::string resolved_path;
2716 if (android::base::Readlink(*path, &resolved_path)) {
2717 *path = resolved_path;
2718 }
2719}
2720
Nandana Dutt4be45d12018-09-26 15:04:23 +01002721/*
2722 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002723 * and adds the version file. Return false if zip_file could not be open to write.
Nandana Dutt4be45d12018-09-26 15:04:23 +01002724 */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002725static bool PrepareToWriteToFile() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002726 MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2727
Nandana Dutt4be45d12018-09-26 15:04:23 +01002728 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2729 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002730 ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002731 char date[80];
2732 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2733 ds.name_ = date;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002734
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002735 if (ds.options_->telephony_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002736 ds.base_name_ += "-telephony";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002737 } else if (ds.options_->wifi_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002738 ds.base_name_ += "-wifi";
2739 }
2740
Paul Chang0d2aad72020-02-13 20:04:03 +08002741 if (ds.options_->do_screenshot) {
Nandana Dutt9d17b942020-03-26 10:02:59 +00002742 ds.screenshot_path_ = ds.GetPath(ds.CalledByApi() ? "-png.tmp" : ".png");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002743 }
2744 ds.tmp_path_ = ds.GetPath(".tmp");
2745 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2746
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01002747 std::string destination = ds.CalledByApi()
Nandana Dutt54dbd672019-01-11 12:58:05 +00002748 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
Nandana Dutt9a76d202019-01-21 15:56:48 +00002749 : ds.bugreport_internal_dir_.c_str();
Nandana Dutt4be45d12018-09-26 15:04:23 +01002750 MYLOGD(
Nandana Dutt235c6672019-11-14 15:22:32 +00002751 "Bugreport dir: [%s] "
2752 "Base name: [%s] "
2753 "Suffix: [%s] "
2754 "Log path: [%s] "
2755 "Temporary path: [%s] "
2756 "Screenshot path: [%s]\n",
Nandana Dutt9a76d202019-01-21 15:56:48 +00002757 destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2758 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002759
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002760 ds.path_ = ds.GetPath(ds.CalledByApi() ? "-zip.tmp" : ".zip");
2761 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2762 create_parent_dirs(ds.path_.c_str());
2763 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2764 if (ds.zip_file == nullptr) {
2765 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2766 return false;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002767 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002768 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2769 ds.AddTextZipEntry("version.txt", ds.version_);
2770 return true;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002771}
2772
2773/*
Abhijeet Kaure370d682019-10-01 16:49:30 +01002774 * Finalizes writing to the file by zipping the tmp file to the final location,
Nandana Dutt4be45d12018-09-26 15:04:23 +01002775 * printing zipped file status, etc.
2776 */
2777static void FinalizeFile() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002778 bool do_text_file = !ds.FinishZipFile();
2779 if (do_text_file) {
2780 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002781 }
mhasank2d75c442020-06-11 15:05:25 -07002782
2783 std::string final_path = ds.path_;
2784 if (ds.options_->OutputToCustomFile()) {
mhasank3a4cfb42020-06-15 18:06:43 -07002785 final_path = ds.GetPath(ds.options_->out_dir, ".zip");
mhasank2d75c442020-06-11 15:05:25 -07002786 android::os::CopyFileToFile(ds.path_, final_path);
2787 }
2788
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002789 if (ds.options_->stream_to_socket) {
2790 android::os::CopyFileToFd(ds.path_, ds.control_socket_fd_);
2791 } else if (ds.options_->progress_updates_to_socket) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002792 if (do_text_file) {
2793 dprintf(ds.control_socket_fd_,
2794 "FAIL:could not create zip file, check %s "
2795 "for more details\n",
2796 ds.log_path_.c_str());
2797 } else {
mhasank2d75c442020-06-11 15:05:25 -07002798 dprintf(ds.control_socket_fd_, "OK:%s\n", final_path.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002799 }
2800 }
2801}
2802
Nandana Dutt4be45d12018-09-26 15:04:23 +01002803
Nandana Dutt58d72e22018-11-16 10:30:48 +00002804static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2805 switch (mode) {
2806 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2807 return "BUGREPORT_FULL";
2808 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2809 return "BUGREPORT_INTERACTIVE";
2810 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2811 return "BUGREPORT_REMOTE";
2812 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2813 return "BUGREPORT_WEAR";
2814 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2815 return "BUGREPORT_TELEPHONY";
2816 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2817 return "BUGREPORT_WIFI";
Elis Elliott8e401ad2023-08-08 11:18:59 +00002818 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
2819 return "BUGREPORT_ONBOARDING";
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002820 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2821 return "BUGREPORT_DEFAULT";
Nandana Dutt58d72e22018-11-16 10:30:48 +00002822 }
2823}
2824
Steven Leeb573eb82022-11-29 22:31:35 +08002825static bool IsConsentlessBugreportAllowed(const Dumpstate::DumpOptions& options) {
2826 // only BUGREPORT_TELEPHONY does not allow using consentless bugreport
2827 return !options.telephony_only;
2828}
2829
Paul Changf59c2b72020-03-10 02:08:55 +08002830static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options,
2831 bool is_screenshot_requested) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002832 // Modify com.android.shell.BugreportProgressService#isDefaultScreenshotRequired as well for
2833 // default system screenshots.
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002834 options->bugreport_mode = mode;
2835 options->bugreport_mode_string = ModeToString(mode);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002836 switch (mode) {
2837 case Dumpstate::BugreportMode::BUGREPORT_FULL:
Paul Changf59c2b72020-03-10 02:08:55 +08002838 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002839 break;
2840 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002841 // Currently, the dumpstate binder is only used by Shell to update progress.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002842 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002843 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002844 break;
2845 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002846 options->do_vibrate = false;
2847 options->is_remote_mode = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002848 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002849 break;
2850 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
Robert Ginda55ecebd2023-04-03 22:53:13 +00002851 options->do_vibrate = false;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002852 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002853 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002854 break;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002855 // TODO(b/148168577) rename TELEPHONY everywhere to CONNECTIVITY.
Nandana Dutt58d72e22018-11-16 10:30:48 +00002856 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002857 options->telephony_only = true;
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002858 options->do_progress_updates = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002859 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002860 break;
2861 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002862 options->wifi_only = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002863 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002864 break;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002865 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
2866 options->onboarding_only = true;
2867 options->do_screenshot = false;
2868 break;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002869 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2870 break;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002871 }
2872}
2873
Nandana Dutt58d72e22018-11-16 10:30:48 +00002874static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
Nandana Dutt235c6672019-11-14 15:22:32 +00002875 MYLOGI(
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002876 "do_vibrate: %d stream_to_socket: %d progress_updates_to_socket: %d do_screenshot: %d "
Rhed Jao25f50e02020-08-20 00:10:32 +08002877 "is_remote_mode: %d show_header_only: %d telephony_only: %d "
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002878 "wifi_only: %d do_progress_updates: %d fd: %d bugreport_mode: %s "
mhasankd451a472020-05-26 18:02:39 -07002879 "limited_only: %d args: %s\n",
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002880 options.do_vibrate, options.stream_to_socket, options.progress_updates_to_socket,
Paul Chang0d2aad72020-02-13 20:04:03 +08002881 options.do_screenshot, options.is_remote_mode, options.show_header_only,
Rhed Jao25f50e02020-08-20 00:10:32 +08002882 options.telephony_only, options.wifi_only,
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002883 options.do_progress_updates, options.bugreport_fd.get(),
2884 options.bugreport_mode_string.c_str(),
2885 options.limited_only, options.args.c_str());
Nandana Dutt58d72e22018-11-16 10:30:48 +00002886}
2887
Nandana Dutt54dbd672019-01-11 12:58:05 +00002888void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
Kean Mariotti306633e2022-09-05 16:30:47 +00002889 int bugreport_flags,
Nandana Dutt54dbd672019-01-11 12:58:05 +00002890 const android::base::unique_fd& bugreport_fd_in,
Paul Changf59c2b72020-03-10 02:08:55 +08002891 const android::base::unique_fd& screenshot_fd_in,
2892 bool is_screenshot_requested) {
Kean Mariotti306633e2022-09-05 16:30:47 +00002893 this->use_predumped_ui_data = bugreport_flags & BugreportFlag::BUGREPORT_USE_PREDUMPED_UI_DATA;
Gavin Corkerya44686c2022-11-23 18:16:51 +00002894 this->is_consent_deferred = bugreport_flags & BugreportFlag::BUGREPORT_FLAG_DEFER_CONSENT;
Nandana Dutt54dbd672019-01-11 12:58:05 +00002895 // Duplicate the fds because the passed in fds don't outlive the binder transaction.
Todd Frederick621533f2022-03-26 02:54:17 +00002896 bugreport_fd.reset(fcntl(bugreport_fd_in.get(), F_DUPFD_CLOEXEC, 0));
2897 screenshot_fd.reset(fcntl(screenshot_fd_in.get(), F_DUPFD_CLOEXEC, 0));
Nandana Dutt58d72e22018-11-16 10:30:48 +00002898
Paul Changf59c2b72020-03-10 02:08:55 +08002899 SetOptionsFromMode(bugreport_mode, this, is_screenshot_requested);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002900}
2901
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002902Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
2903 RunStatus status = RunStatus::OK;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002904 int c;
mhasankd451a472020-05-26 18:02:39 -07002905 while ((c = getopt(argc, argv, "dho:svqzpLPBRSV:w")) != -1) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002906 switch (c) {
2907 // clang-format off
mhasank3a4cfb42020-06-15 18:06:43 -07002908 case 'o': out_dir = optarg; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002909 case 's': stream_to_socket = true; break;
2910 case 'S': progress_updates_to_socket = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002911 case 'v': show_header_only = true; break;
2912 case 'q': do_vibrate = false; break;
Paul Chang0d2aad72020-02-13 20:04:03 +08002913 case 'p': do_screenshot = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002914 case 'P': do_progress_updates = true; break;
2915 case 'R': is_remote_mode = true; break;
mhasankd451a472020-05-26 18:02:39 -07002916 case 'L': limited_only = true; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002917 case 'V':
2918 case 'd':
2919 case 'z':
2920 // compatibility no-op
2921 break;
Nandana Dutt235864b2019-01-22 12:10:16 +00002922 case 'w':
2923 // This was already processed
2924 break;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002925 case 'h':
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002926 status = RunStatus::HELP;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002927 break;
2928 default:
2929 fprintf(stderr, "Invalid option: %c\n", c);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002930 status = RunStatus::INVALID_INPUT;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002931 break;
2932 // clang-format on
2933 }
2934 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08002935
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002936 for (int i = 0; i < argc; i++) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002937 args += argv[i];
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002938 if (i < argc - 1) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002939 args += " ";
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002940 }
2941 }
2942
2943 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
2944 optind = 1;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002945
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002946 return status;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002947}
2948
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002949bool Dumpstate::DumpOptions::ValidateOptions() const {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002950 if (bugreport_fd.get() != -1 && stream_to_socket) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002951 return false;
2952 }
2953
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002954 if ((progress_updates_to_socket || do_progress_updates) && stream_to_socket) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002955 return false;
2956 }
2957
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002958 if (is_remote_mode && (do_progress_updates || stream_to_socket)) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002959 return false;
2960 }
2961 return true;
2962}
2963
Nandana Dutt197661d2018-11-16 16:40:21 +00002964void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
2965 options_ = std::move(options);
2966}
2967
Abhijeet Kaura407fb82020-03-27 12:51:12 +00002968void Dumpstate::Initialize() {
2969 /* gets the sequential id */
2970 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
2971 id_ = ++last_id;
2972 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
2973}
2974
Nandana Duttd2f5f082019-01-18 17:13:52 +00002975Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
2976 Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
Gavin Corkerya44686c2022-11-23 18:16:51 +00002977 HandleRunStatus(status);
2978 return status;
2979}
2980
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00002981Dumpstate::RunStatus Dumpstate::Retrieve(int32_t calling_uid, const std::string& calling_package,
2982 const bool keep_bugreport_on_retrieval) {
2983 Dumpstate::RunStatus status = RetrieveInternal(calling_uid, calling_package,
2984 keep_bugreport_on_retrieval);
Gavin Corkerya44686c2022-11-23 18:16:51 +00002985 HandleRunStatus(status);
2986 return status;
2987}
2988
2989Dumpstate::RunStatus Dumpstate::RetrieveInternal(int32_t calling_uid,
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00002990 const std::string& calling_package,
2991 const bool keep_bugreport_on_retrieval) {
Gavin Corkerya44686c2022-11-23 18:16:51 +00002992 consent_callback_ = new ConsentCallback();
2993 const String16 incidentcompanion("incidentcompanion");
2994 sp<android::IBinder> ics(
2995 defaultServiceManager()->checkService(incidentcompanion));
2996 android::String16 package(calling_package.c_str());
2997 if (ics != nullptr) {
2998 MYLOGD("Checking user consent via incidentcompanion service\n");
2999 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
3000 calling_uid, package, String16(), String16(),
3001 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
3002 } else {
3003 MYLOGD(
3004 "Unable to check user consent; incidentcompanion service unavailable\n");
3005 return RunStatus::USER_CONSENT_TIMED_OUT;
3006 }
3007 UserConsentResult consent_result = consent_callback_->getResult();
3008 int timeout_ms = 30 * 1000;
3009 while (consent_result == UserConsentResult::UNAVAILABLE &&
3010 consent_callback_->getElapsedTimeMs() < timeout_ms) {
3011 sleep(1);
3012 consent_result = consent_callback_->getResult();
3013 }
3014 if (consent_result == UserConsentResult::DENIED) {
3015 return RunStatus::USER_CONSENT_DENIED;
3016 }
3017 if (consent_result == UserConsentResult::UNAVAILABLE) {
3018 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3019 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3020 consent_callback_.get());
3021 return RunStatus::USER_CONSENT_TIMED_OUT;
3022 }
3023
3024 bool copy_succeeded =
3025 android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003026
3027 if (copy_succeeded && (!android::app::admin::flags::onboarding_bugreport_v2_enabled()
3028 || !keep_bugreport_on_retrieval)) {
3029 android::os::UnlinkAndLogOnError(path_);
Gavin Corkerya44686c2022-11-23 18:16:51 +00003030 }
Kholoud Mohamed7c3fb7c2023-10-18 12:56:22 +00003031
Gavin Corkerya44686c2022-11-23 18:16:51 +00003032 return copy_succeeded ? Dumpstate::RunStatus::OK
3033 : Dumpstate::RunStatus::ERROR;
3034}
3035
3036void Dumpstate::HandleRunStatus(Dumpstate::RunStatus status) {
3037 if (listener_ != nullptr) {
Nandana Duttbabf6c72019-01-15 14:11:12 +00003038 switch (status) {
3039 case Dumpstate::RunStatus::OK:
Gavin Corkerya44686c2022-11-23 18:16:51 +00003040 listener_->onFinished(path_.c_str());
Nandana Duttbabf6c72019-01-15 14:11:12 +00003041 break;
3042 case Dumpstate::RunStatus::HELP:
3043 break;
3044 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003045 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00003046 break;
3047 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003048 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
3049 break;
3050 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3051 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
3052 break;
3053 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
3054 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00003055 break;
3056 }
3057 }
Nandana Duttbabf6c72019-01-15 14:11:12 +00003058}
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003059void Dumpstate::Cancel() {
3060 CleanupTmpFiles();
3061 android::os::UnlinkAndLogOnError(log_path_);
3062 for (int i = 0; i < NUM_OF_DUMPS; i++) {
3063 android::os::UnlinkAndLogOnError(ds.bugreport_internal_dir_ + "/" +
3064 kDumpstateBoardFiles[i]);
3065 }
3066 tombstone_data_.clear();
3067 anr_data_.clear();
Woody Lin20767a92022-11-29 15:50:24 +08003068 shutdown_checkpoints_.clear();
Rhed Jao0daac912020-08-21 14:48:20 +08003069
3070 // Instead of shutdown the pool, we delete temporary files directly since
3071 // shutdown blocking the call.
3072 if (dump_pool_) {
3073 dump_pool_->deleteTempFiles();
3074 }
3075 if (zip_entry_tasks_) {
3076 zip_entry_tasks_->run(/*do_cancel =*/ true);
3077 }
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003078}
3079
Kean Mariotti306633e2022-09-05 16:30:47 +00003080void Dumpstate::PreDumpUiData() {
3081 MaybeSnapshotUiTraces();
3082}
3083
Nandana Dutt979388e2018-11-30 16:48:55 +00003084/*
3085 * Dumps relevant information to a bugreport based on the given options.
3086 *
3087 * The bugreport can be dumped to a file or streamed to a socket.
3088 *
3089 * How dumping to file works:
3090 * stdout is redirected to a temporary file. This will later become the main bugreport entry.
3091 * stderr is redirected a log file.
3092 *
3093 * The temporary bugreport is then populated via printfs, dumping contents of files and
3094 * output of commands to stdout.
3095 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003096 * A bunch of other files and dumps are added to the zip archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00003097 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003098 * The temporary bugreport file and the log file also get added to the archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00003099 *
mhasank2d75c442020-06-11 15:05:25 -07003100 * Bugreports are first generated in a local directory and later copied to the caller's fd
3101 * or directory if supplied.
Nandana Dutt979388e2018-11-30 16:48:55 +00003102 */
Nandana Duttd2f5f082019-01-18 17:13:52 +00003103Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
3104 const std::string& calling_package) {
Rhed Jao5377d792020-07-16 17:37:39 +08003105 DurationReporter duration_reporter("RUN INTERNAL", /* logcat_only = */true);
Nandana Dutt979388e2018-11-30 16:48:55 +00003106 LogDumpOptions(*options_);
Nandana Dutt197661d2018-11-16 16:40:21 +00003107 if (!options_->ValidateOptions()) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00003108 MYLOGE("Invalid options specified\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003109 return RunStatus::INVALID_INPUT;
3110 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003111 /* set as high priority, and protect from OOM killer */
3112 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003113
Felipe Lemed071c682016-10-20 16:48:00 -07003114 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07003115 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003116 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003117 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003118 } else {
3119 /* fallback to kernels <= 2.6.35 */
3120 oom_adj = fopen("/proc/self/oom_adj", "we");
3121 if (oom_adj) {
3122 fputs("-17", oom_adj);
3123 fclose(oom_adj);
3124 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003125 }
3126
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003127 if (version_ == VERSION_DEFAULT) {
3128 version_ = VERSION_CURRENT;
Michal Karpinski4db754f2015-12-11 18:04:32 +00003129 }
3130
Chris Morin5a50d482022-02-01 17:41:18 -08003131 if (version_ != VERSION_CURRENT) {
3132 MYLOGE("invalid version requested ('%s'); supported values are: ('%s', '%s')\n",
3133 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003134 return RunStatus::INVALID_INPUT;
Felipe Lemed071c682016-10-20 16:48:00 -07003135 }
3136
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003137 if (options_->show_header_only) {
3138 PrintHeader();
3139 return RunStatus::OK;
Felipe Lemed071c682016-10-20 16:48:00 -07003140 }
3141
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003142 MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n",
3143 calling_uid, calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003144
Felipe Leme7447d7c2016-11-03 18:12:22 -07003145 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003146 std::string stats_path =
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003147 android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003148 progress_.reset(new Progress(stats_path));
Felipe Leme7447d7c2016-11-03 18:12:22 -07003149
Sahana Raof35ed432019-07-12 10:47:52 +01003150 if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
3151 MYLOGE("Failed to acquire wake lock: %s\n", strerror(errno));
3152 } else {
3153 // Wake lock will be released automatically on process death
3154 MYLOGD("Wake lock acquired.\n");
3155 }
3156
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08003157 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07003158
Felipe Lemef0292972016-11-22 13:57:05 -08003159 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07003160 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
3161 }
3162
Kevin Jeonfa64e642023-07-27 11:36:41 -04003163 if (PropertiesHelper::IsStrictRun()) {
3164 MYLOGI(
3165 "Running on strict-run mode, which has shorter timeouts "
3166 "(to disable, call 'setprop dumpstate.strict_run false')\n");
3167 }
3168
Nandana Dutt235c6672019-11-14 15:22:32 +00003169 MYLOGI("dumpstate info: id=%d, args='%s', bugreport_mode= %s bugreport format version: %s\n",
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00003170 id_, options_->args.c_str(), options_->bugreport_mode_string.c_str(), version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08003171
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003172 do_early_screenshot_ = options_->do_progress_updates;
Felipe Lemee338bf62015-12-07 14:03:50 -08003173
Christopher Ferrised9354f2014-10-01 17:35:01 -07003174 // If we are going to use a socket, do it as early as possible
3175 // to avoid timeouts from bugreport.
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003176 if (options_->stream_to_socket || options_->progress_updates_to_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07003177 MYLOGD("Opening control socket\n");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003178 control_socket_fd_ = open_socket_fn_("dumpstate");
Nandana Dutta344cb62019-02-22 15:12:35 +00003179 if (control_socket_fd_ == -1) {
3180 return ERROR;
3181 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003182 if (options_->progress_updates_to_socket) {
3183 options_->do_progress_updates = 1;
3184 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07003185 }
3186
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003187 if (!PrepareToWriteToFile()) {
3188 return ERROR;
3189 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08003190
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003191 // Interactive, wear & telephony modes are default to true.
3192 // and may enable from cli option or when using control socket
3193 if (options_->do_progress_updates) {
3194 // clang-format off
3195 std::vector<std::string> am_args = {
3196 "--receiver-permission", "android.permission.DUMP",
3197 };
3198 // clang-format on
3199 // Send STARTED broadcast for apps that listen to bugreport generation events
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003200 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED",
3201 am_args, multiuser_get_user_id(calling_uid));
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003202 if (options_->progress_updates_to_socket) {
3203 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08003204 }
3205 }
3206
Nick Kralevichf3599b32016-01-25 15:05:16 -08003207 /* read /proc/cmdline before dropping root */
3208 FILE *cmdline = fopen("/proc/cmdline", "re");
3209 if (cmdline) {
3210 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
3211 fclose(cmdline);
3212 }
3213
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003214 if (options_->do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08003215 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05003216 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003217
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003218 if (zip_file != nullptr) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003219 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
3220 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003221 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08003222 }
3223 }
3224
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003225 int dup_stdout_fd;
3226 int dup_stderr_fd;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003227 // Redirect stderr to log_path_ for debugging.
3228 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
3229 if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
3230 return ERROR;
3231 }
3232 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
3233 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
3234 strerror(errno));
3235 }
Nandana Dutt979388e2018-11-30 16:48:55 +00003236
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003237 // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
3238 // moved into zip file later, if zipping.
3239 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
3240 // TODO: why not write to a file instead of stdout to overcome this problem?
3241 /* TODO: rather than generating a text file now and zipping it later,
3242 it would be more efficient to redirect stdout to the zip entry
3243 directly, but the libziparchive doesn't support that option yet. */
3244 if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
3245 return ERROR;
3246 }
3247 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
3248 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
3249 tmp_path_.c_str(), strerror(errno));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003250 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08003251
3252 // Don't buffer stdout
3253 setvbuf(stdout, nullptr, _IONBF, 0);
3254
Rhed Jao5377d792020-07-16 17:37:39 +08003255 // Enable the parallel run if the client requests to output to a file.
3256 EnableParallelRunIfNeeded();
3257 // Using scope guard to make sure the dump pool can be shut down correctly.
3258 auto scope_guard_to_shutdown_pool = android::base::make_scope_guard([=]() {
3259 ShutdownDumpPool();
3260 });
3261
Felipe Leme608385d2016-02-01 10:35:38 -08003262 // NOTE: there should be no stdout output until now, otherwise it would break the header.
3263 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08003264 // duration is logged into MYLOG instead.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003265 PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003266
Gavin Corkery6968f552020-11-22 18:09:05 +00003267 bool is_dumpstate_restricted = options_->telephony_only
3268 || options_->wifi_only
3269 || options_->limited_only;
3270 if (!is_dumpstate_restricted) {
Paul Chang0d2aad72020-02-13 20:04:03 +08003271 // Invoke critical dumpsys first to preserve system state, before doing anything else.
Jichao Lie89d9c12019-11-21 19:02:51 -08003272 RunDumpsysCritical();
Gavin Corkery6968f552020-11-22 18:09:05 +00003273 }
3274 MaybeTakeEarlyScreenshot();
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003275
3276 if (!is_dumpstate_restricted) {
3277 // Snapshot the system trace now (if running) to avoid that dumpstate's
3278 // own activity pushes out interesting data from the trace ring buffer.
3279 // The trace file is added to the zip by MaybeAddSystemTraceToZip().
3280 MaybeSnapshotSystemTrace();
Yohei Yukawa95305b32021-03-09 07:54:27 -08003281
Kean Mariotti306633e2022-09-05 16:30:47 +00003282 // Snapshot the UI traces now (if running).
3283 // The trace files will be added to bugreport later.
3284 MaybeSnapshotUiTraces();
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003285 }
Gavin Corkery6968f552020-11-22 18:09:05 +00003286 onUiIntensiveBugreportDumpsFinished(calling_uid);
3287 MaybeCheckUserConsent(calling_uid, calling_package);
3288 if (options_->telephony_only) {
3289 DumpstateTelephonyOnly(calling_package);
3290 } else if (options_->wifi_only) {
3291 DumpstateWifiOnly();
3292 } else if (options_->limited_only) {
3293 DumpstateLimitedOnly();
Elis Elliott8e401ad2023-08-08 11:18:59 +00003294 } else if (options_->onboarding_only) {
3295 DumpstateOnboardingOnly();
Gavin Corkery6968f552020-11-22 18:09:05 +00003296 } else {
Nandana Dutt4be45d12018-09-26 15:04:23 +01003297 // Dump state for the default case. This also drops root.
Jichao Lie89d9c12019-11-21 19:02:51 -08003298 RunStatus s = DumpstateDefaultAfterCritical();
Nandana Dutt5c390032019-03-12 10:52:56 +00003299 if (s != RunStatus::OK) {
Nandana Duttaac6f582019-07-26 14:32:47 +01003300 if (s == RunStatus::USER_CONSENT_DENIED) {
Nandana Dutt5c390032019-03-12 10:52:56 +00003301 HandleUserConsentDenied();
3302 }
3303 return s;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08003304 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07003305 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07003306
Felipe Leme55b42a62015-11-10 17:39:08 -08003307 /* close output if needed */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003308 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003309
Abhijeet Kaure370d682019-10-01 16:49:30 +01003310 // Zip the (now complete) .tmp file within the internal directory.
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003311 ATRACE_BEGIN("FinalizeFile");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003312 FinalizeFile();
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003313 ATRACE_END();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003314
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003315 // Share the final file with the caller if the user has consented or Shell is the caller.
Nandana Duttd2f5f082019-01-18 17:13:52 +00003316 Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
Gavin Corkerya44686c2022-11-23 18:16:51 +00003317 if (CalledByApi() && !options_->is_consent_deferred) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003318 status = CopyBugreportIfUserConsented(calling_uid);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003319 if (status != Dumpstate::RunStatus::OK &&
3320 status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3321 // Do an early return if there were errors. We make an exception for consent
3322 // timing out because it's possible the user got distracted. In this case the
3323 // bugreport is not shared but made available for manual retrieval.
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003324 MYLOGI("User denied consent. Returning\n");
Nandana Duttd2f5f082019-01-18 17:13:52 +00003325 return status;
3326 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003327 if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3328 MYLOGI(
3329 "Did not receive user consent yet."
3330 " Will not copy the bugreport artifacts to caller.\n");
Abhijeet Kaur57627412019-04-17 16:00:09 +01003331 const String16 incidentcompanion("incidentcompanion");
3332 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
3333 if (ics != nullptr) {
3334 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3335 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3336 consent_callback_.get());
3337 } else {
3338 MYLOGD("Unable to cancel user consent; incidentcompanion service unavailable\n");
3339 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003340 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003341 }
3342
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003343 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003344 if (options_->do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09003345 for (int i = 0; i < 3; i++) {
3346 Vibrate(75);
3347 usleep((75 + 50) * 1000);
3348 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003349 }
3350
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003351 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
3352 progress_->GetInitialMax());
3353 progress_->Save();
3354 MYLOGI("done (id %d)\n", id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003355
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003356 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08003357
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003358 if (control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07003359 MYLOGD("Closing control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003360 close(control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07003361 }
3362
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003363 tombstone_data_.clear();
3364 anr_data_.clear();
Woody Lin20767a92022-11-29 15:50:24 +08003365 shutdown_checkpoints_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01003366
Nandana Duttd2f5f082019-01-18 17:13:52 +00003367 return (consent_callback_ != nullptr &&
3368 consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
3369 ? USER_CONSENT_TIMED_OUT
3370 : RunStatus::OK;
3371}
3372
Paul Chang0d2aad72020-02-13 20:04:03 +08003373void Dumpstate::MaybeTakeEarlyScreenshot() {
3374 if (!options_->do_screenshot || !do_early_screenshot_) {
3375 return;
3376 }
3377
3378 TakeScreenshot();
3379}
3380
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003381void Dumpstate::MaybeSnapshotSystemTrace() {
3382 // If a background system trace is happening and is marked as "suitable for
3383 // bugreport" (i.e. bugreport_score > 0 in the trace config), this command
3384 // will stop it and serialize into SYSTEM_TRACE_SNAPSHOT. In the (likely)
3385 // case that no trace is ongoing, this command is a no-op.
3386 // Note: this should not be enqueued as we need to freeze the trace before
3387 // dumpstate starts. Otherwise the trace ring buffers will contain mostly
3388 // the dumpstate's own activity which is irrelevant.
3389 int res = RunCommand(
3390 "SERIALIZE PERFETTO TRACE",
3391 {"perfetto", "--save-for-bugreport"},
3392 CommandOptions::WithTimeout(10)
3393 .DropRoot()
3394 .CloseAllFileDescriptorsOnExec()
3395 .Build());
3396 has_system_trace_ = res == 0;
3397 // MaybeAddSystemTraceToZip() will take care of copying the trace in the zip
3398 // file in the later stages.
3399}
3400
Kean Mariotti306633e2022-09-05 16:30:47 +00003401void Dumpstate::MaybeSnapshotUiTraces() {
3402 if (PropertiesHelper::IsUserBuild() || options_->use_predumped_ui_data) {
3403 return;
3404 }
3405
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003406 const std::vector<std::vector<std::string>> dumpTracesForBugReportCommands = {
3407 {"dumpsys", "activity", "service", "SystemUIService", "WMShell", "protolog",
3408 "save-for-bugreport"},
3409 {"dumpsys", "activity", "service", "SystemUIService", "WMShell", "transitions", "tracing",
3410 "save-for-bugreport"},
3411 {"cmd", "input_method", "tracing", "save-for-bugreport"},
3412 {"cmd", "window", "tracing", "save-for-bugreport"},
3413 {"cmd", "window", "shell", "tracing", "save-for-bugreport"},
3414 };
Hongwei Wang39229132023-01-24 15:09:59 -08003415
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003416 for (const auto& command : dumpTracesForBugReportCommands) {
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003417 RunCommand(
3418 // Empty name because it's not intended to be classified as a bugreport section.
3419 // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003420 "", command,
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003421 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
3422 }
Kean Mariotti306633e2022-09-05 16:30:47 +00003423
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003424 // This command needs to be run as root
Kean Mariotti306633e2022-09-05 16:30:47 +00003425 static const auto SURFACEFLINGER_COMMAND_SAVE_ALL_TRACES = std::vector<std::string> {
3426 "service", "call", "SurfaceFlinger", "1042"
3427 };
3428 // Empty name because it's not intended to be classified as a bugreport section.
3429 // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
3430 RunCommand(
3431 "", SURFACEFLINGER_COMMAND_SAVE_ALL_TRACES,
3432 CommandOptions::WithTimeout(10).Always().AsRoot().RedirectStderr().Build());
3433}
3434
3435void Dumpstate::MaybePostProcessUiTraces() {
3436 if (PropertiesHelper::IsUserBuild()) {
3437 return;
3438 }
3439
3440 RunCommand(
3441 // Empty name because it's not intended to be classified as a bugreport section.
3442 // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
3443 "", {
3444 "/system/xbin/su", "system",
3445 "/system/bin/layertracegenerator",
3446 "/data/misc/wmtrace/transactions_trace.winscope",
3447 "/data/misc/wmtrace/layers_trace_from_transactions.winscope"
3448 },
3449 CommandOptions::WithTimeout(120).Always().RedirectStderr().Build());
3450}
3451
3452void Dumpstate::MaybeAddUiTracesToZip() {
3453 if (PropertiesHelper::IsUserBuild()) {
3454 return;
3455 }
3456
3457 ds.AddDir(WMTRACE_DATA_DIR, false);
Yohei Yukawa95305b32021-03-09 07:54:27 -08003458}
3459
Paul Changeb4b4642020-05-28 22:05:47 +08003460void Dumpstate::onUiIntensiveBugreportDumpsFinished(int32_t calling_uid) {
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003461 if (multiuser_get_app_id(calling_uid) == AID_SHELL || !CalledByApi()) {
Paul Changc490e662020-04-11 18:14:09 +08003462 return;
3463 }
3464 if (listener_ != nullptr) {
3465 // Let listener know ui intensive bugreport dumps are finished, then it can do event
3466 // handling if required.
Paul Changeb4b4642020-05-28 22:05:47 +08003467 listener_->onUiIntensiveBugreportDumpsFinished();
Paul Changc490e662020-04-11 18:14:09 +08003468 }
3469}
3470
Jichao Lie89d9c12019-11-21 19:02:51 -08003471void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) {
Gavin Corkerya44686c2022-11-23 18:16:51 +00003472 if (multiuser_get_app_id(calling_uid) == AID_SHELL ||
3473 !CalledByApi() || options_->is_consent_deferred) {
3474 // No need to get consent for shell triggered dumpstates, or not
3475 // through bugreporting API (i.e. no fd to copy back), or when consent
3476 // is deferred.
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003477 return;
3478 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003479 consent_callback_ = new ConsentCallback();
3480 const String16 incidentcompanion("incidentcompanion");
3481 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
Jichao Lie89d9c12019-11-21 19:02:51 -08003482 android::String16 package(calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003483 if (ics != nullptr) {
3484 MYLOGD("Checking user consent via incidentcompanion service\n");
Steven Leeb573eb82022-11-29 22:31:35 +08003485 int flags = 0x1; // IncidentManager.FLAG_CONFIRMATION_DIALOG
3486 if (IsConsentlessBugreportAllowed(*options_)) {
3487 flags |= 0x2; // IncidentManager.FLAG_ALLOW_CONSENTLESS_BUGREPORT
3488 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003489 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
Steven Leeb573eb82022-11-29 22:31:35 +08003490 calling_uid, package, String16(), String16(), flags, consent_callback_.get());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003491 } else {
3492 MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
3493 }
3494}
3495
Nandana Dutt5c390032019-03-12 10:52:56 +00003496bool Dumpstate::IsUserConsentDenied() const {
3497 return ds.consent_callback_ != nullptr &&
3498 ds.consent_callback_->getResult() == UserConsentResult::DENIED;
3499}
3500
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01003501bool Dumpstate::CalledByApi() const {
3502 return ds.options_->bugreport_fd.get() != -1 ? true : false;
3503}
3504
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003505void Dumpstate::CleanupTmpFiles() {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003506 android::os::UnlinkAndLogOnError(tmp_path_);
3507 android::os::UnlinkAndLogOnError(screenshot_path_);
3508 android::os::UnlinkAndLogOnError(path_);
Gavin Corkery789d7a52021-02-24 23:52:35 +00003509 if (dump_traces_path != nullptr) {
3510 android::os::UnlinkAndLogOnError(dump_traces_path);
3511 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003512}
3513
Rhed Jao5377d792020-07-16 17:37:39 +08003514void Dumpstate::EnableParallelRunIfNeeded() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003515 if (!PropertiesHelper::IsParallelRun()) {
Rhed Jao5377d792020-07-16 17:37:39 +08003516 return;
3517 }
3518 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003519 zip_entry_tasks_ = std::make_unique<TaskQueue>();
Rhed Jao5377d792020-07-16 17:37:39 +08003520}
3521
3522void Dumpstate::ShutdownDumpPool() {
3523 if (dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08003524 dump_pool_.reset();
Rhed Jao5377d792020-07-16 17:37:39 +08003525 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003526 if (zip_entry_tasks_) {
3527 zip_entry_tasks_->run(/* do_cancel = */true);
3528 zip_entry_tasks_ = nullptr;
3529 }
3530}
3531
3532void Dumpstate::EnqueueAddZipEntryAndCleanupIfNeeded(const std::string& entry_name,
3533 const std::string& entry_path) {
3534 auto func_add_zip_entry_and_cleanup = [=](bool task_cancelled) {
3535 if (!task_cancelled) {
3536 AddZipEntry(entry_name, entry_path);
3537 }
3538 android::os::UnlinkAndLogOnError(entry_path);
3539 };
3540 if (zip_entry_tasks_) {
3541 // Enqueues AddZipEntryAndCleanup function if the parallel run is enabled.
3542 zip_entry_tasks_->add(func_add_zip_entry_and_cleanup, _1);
3543 } else {
3544 // Invokes AddZipEntryAndCleanup immediately
3545 std::invoke(func_add_zip_entry_and_cleanup, /* task_cancelled = */false);
3546 }
Rhed Jao5377d792020-07-16 17:37:39 +08003547}
3548
Nandana Duttd2f5f082019-01-18 17:13:52 +00003549Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
3550 MYLOGD("User denied consent; deleting files and returning\n");
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003551 CleanupTmpFiles();
Nandana Duttd2f5f082019-01-18 17:13:52 +00003552 return USER_CONSENT_DENIED;
3553}
3554
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003555Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented(int32_t calling_uid) {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003556 // If the caller has asked to copy the bugreport over to their directory, we need explicit
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003557 // user consent (unless the caller is Shell).
3558 UserConsentResult consent_result;
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003559 if (multiuser_get_app_id(calling_uid) == AID_SHELL) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003560 consent_result = UserConsentResult::APPROVED;
3561 } else {
3562 consent_result = consent_callback_->getResult();
3563 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003564 if (consent_result == UserConsentResult::UNAVAILABLE) {
3565 // User has not responded yet.
3566 uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
Hunter Knepshield70610fa2020-01-03 15:27:33 -08003567 // Telephony is a fast report type, particularly on user builds where information may be
3568 // more aggressively limited. To give the user time to read the consent dialog, increase the
3569 // timeout.
3570 uint64_t timeout_ms = options_->telephony_only ? TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS
3571 : USER_CONSENT_TIMEOUT_MS;
3572 if (elapsed_ms < timeout_ms) {
3573 uint delay_seconds = (timeout_ms - elapsed_ms) / 1000;
Nandana Duttd2f5f082019-01-18 17:13:52 +00003574 MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
3575 sleep(delay_seconds);
3576 }
3577 consent_result = consent_callback_->getResult();
3578 }
3579 if (consent_result == UserConsentResult::DENIED) {
3580 // User has explicitly denied sharing with the app. To be safe delete the
3581 // internal bugreport & tmp files.
3582 return HandleUserConsentDenied();
3583 }
3584 if (consent_result == UserConsentResult::APPROVED) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00003585 bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
3586 if (copy_succeeded) {
3587 android::os::UnlinkAndLogOnError(path_);
Abhijeet Kaur9ce94672020-04-01 17:22:36 +01003588 if (options_->do_screenshot &&
3589 options_->screenshot_fd.get() != -1 &&
3590 !options_->is_screenshot_copied) {
3591 copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
3592 options_->screenshot_fd.get());
3593 options_->is_screenshot_copied = copy_succeeded;
3594 if (copy_succeeded) {
3595 android::os::UnlinkAndLogOnError(screenshot_path_);
3596 }
3597 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003598 }
3599 return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
3600 } else if (consent_result == UserConsentResult::UNAVAILABLE) {
3601 // consent_result is still UNAVAILABLE. The user has likely not responded yet.
3602 // Since we do not have user consent to share the bugreport it does not get
3603 // copied over to the calling app but remains in the internal directory from
3604 // where the user can manually pull it.
Paul Changce644212021-05-11 16:06:45 +08003605 std::string final_path = GetPath(".zip");
3606 bool copy_succeeded = android::os::CopyFileToFile(path_, final_path);
3607 if (copy_succeeded) {
3608 android::os::UnlinkAndLogOnError(path_);
3609 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003610 return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
3611 }
3612 // Unknown result; must be a programming error.
3613 MYLOGE("Unknown user consent result:%d\n", consent_result);
3614 return Dumpstate::RunStatus::ERROR;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003615}
3616
Nandana Duttf02564e2019-02-15 15:24:24 +00003617Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003618 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
3619 Dumpstate::RunStatus status = options->Initialize(argc, argv);
3620 if (status == Dumpstate::RunStatus::OK) {
Nandana Duttf02564e2019-02-15 15:24:24 +00003621 SetOptions(std::move(options));
Nandana Duttd2f5f082019-01-18 17:13:52 +00003622 // When directly running dumpstate binary, the output is not expected to be written
3623 // to any external file descriptor.
Nandana Duttf02564e2019-02-15 15:24:24 +00003624 assert(options_->bugreport_fd.get() == -1);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003625
3626 // calling_uid and calling_package are for user consent to share the bugreport with
Abhijeet Kaura407fb82020-03-27 12:51:12 +00003627 // an app; they are irrelevant here because bugreport is triggered via command line.
3628 // Update Last ID before calling Run().
3629 Initialize();
Nikhil Kumarb70622a2023-06-15 15:37:19 +01003630 status = Run(0 /* calling_uid */, "" /* calling_package */);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003631 }
Nandana Duttf02564e2019-02-15 15:24:24 +00003632 return status;
3633}
3634
3635/* Main entry point for dumpstate binary. */
3636int run_main(int argc, char* argv[]) {
3637 Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003638
3639 switch (status) {
3640 case Dumpstate::RunStatus::OK:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003641 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003642 case Dumpstate::RunStatus::HELP:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003643 ShowUsage();
3644 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003645 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003646 fprintf(stderr, "Invalid combination of args\n");
3647 ShowUsage();
3648 exit(1);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003649 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003650 FALLTHROUGH_INTENDED;
3651 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3652 FALLTHROUGH_INTENDED;
3653 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003654 exit(2);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003655 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003656}
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003657
3658// TODO(111441001): Default DumpOptions to sensible values.
3659Dumpstate::Dumpstate(const std::string& version)
3660 : pid_(getpid()),
3661 options_(new Dumpstate::DumpOptions()),
Nandana Dutt402a8392019-06-14 14:25:13 +01003662 last_reported_percent_progress_(0),
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003663 version_(version),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003664 now_(time(nullptr)),
3665 open_socket_fn_(open_socket) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003666}
3667
3668Dumpstate& Dumpstate::GetInstance() {
3669 static Dumpstate singleton_(android::base::GetProperty("dumpstate.version", VERSION_CURRENT));
3670 return singleton_;
3671}
3672
Rhed Jao5377d792020-07-16 17:37:39 +08003673DurationReporter::DurationReporter(const std::string& title, bool logcat_only, bool verbose,
3674 int duration_fd) : title_(title), logcat_only_(logcat_only), verbose_(verbose),
3675 duration_fd_(duration_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003676 if (!title_.empty()) {
3677 started_ = Nanotime();
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003678 if (title_.find("SHOW MAP") == std::string::npos) {
3679 ATRACE_ASYNC_BEGIN(title_.c_str(), 0);
3680 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003681 }
3682}
3683
3684DurationReporter::~DurationReporter() {
3685 if (!title_.empty()) {
3686 float elapsed = (float)(Nanotime() - started_) / NANOS_PER_SEC;
chenqiwuaf8b2d92019-12-12 18:53:51 +08003687 if (elapsed >= .5f || verbose_) {
3688 MYLOGD("Duration of '%s': %.2fs\n", title_.c_str(), elapsed);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003689 }
chenqiwuaf8b2d92019-12-12 18:53:51 +08003690 if (!logcat_only_) {
3691 // Use "Yoda grammar" to make it easier to grep|sort sections.
Rhed Jao5377d792020-07-16 17:37:39 +08003692 dprintf(duration_fd_, "------ %.3fs was the duration of '%s' ------\n",
3693 elapsed, title_.c_str());
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003694 }
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003695 if (title_.find("SHOW MAP") == std::string::npos) {
3696 ATRACE_ASYNC_END(title_.c_str(), 0);
3697 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003698 }
3699}
3700
3701const int32_t Progress::kDefaultMax = 5000;
3702
3703Progress::Progress(const std::string& path) : Progress(Progress::kDefaultMax, 1.1, path) {
3704}
3705
3706Progress::Progress(int32_t initial_max, int32_t progress, float growth_factor)
3707 : Progress(initial_max, growth_factor, "") {
3708 progress_ = progress;
3709}
3710
3711Progress::Progress(int32_t initial_max, float growth_factor, const std::string& path)
3712 : initial_max_(initial_max),
3713 progress_(0),
3714 max_(initial_max),
3715 growth_factor_(growth_factor),
3716 n_runs_(0),
3717 average_max_(0),
3718 path_(path) {
3719 if (!path_.empty()) {
3720 Load();
3721 }
3722}
3723
3724void Progress::Load() {
3725 MYLOGD("Loading stats from %s\n", path_.c_str());
3726 std::string content;
3727 if (!android::base::ReadFileToString(path_, &content)) {
3728 MYLOGI("Could not read stats from %s; using max of %d\n", path_.c_str(), max_);
3729 return;
3730 }
3731 if (content.empty()) {
3732 MYLOGE("No stats (empty file) on %s; using max of %d\n", path_.c_str(), max_);
3733 return;
3734 }
3735 std::vector<std::string> lines = android::base::Split(content, "\n");
3736
3737 if (lines.size() < 1) {
3738 MYLOGE("Invalid stats on file %s: not enough lines (%d). Using max of %d\n", path_.c_str(),
3739 (int)lines.size(), max_);
3740 return;
3741 }
3742 char* ptr;
3743 n_runs_ = strtol(lines[0].c_str(), &ptr, 10);
3744 average_max_ = strtol(ptr, nullptr, 10);
3745 if (n_runs_ <= 0 || average_max_ <= 0 || n_runs_ > STATS_MAX_N_RUNS ||
3746 average_max_ > STATS_MAX_AVERAGE) {
3747 MYLOGE("Invalid stats line on file %s: %s\n", path_.c_str(), lines[0].c_str());
3748 initial_max_ = Progress::kDefaultMax;
3749 } else {
3750 initial_max_ = average_max_;
3751 }
3752 max_ = initial_max_;
3753
3754 MYLOGI("Average max progress: %d in %d runs; estimated max: %d\n", average_max_, n_runs_, max_);
3755}
3756
3757void Progress::Save() {
3758 int32_t total = n_runs_ * average_max_ + progress_;
3759 int32_t runs = n_runs_ + 1;
3760 int32_t average = floor(((float)total) / runs);
3761 MYLOGI("Saving stats (total=%d, runs=%d, average=%d) on %s\n", total, runs, average,
3762 path_.c_str());
3763 if (path_.empty()) {
3764 return;
3765 }
3766
3767 std::string content = android::base::StringPrintf("%d %d\n", runs, average);
3768 if (!android::base::WriteStringToFile(content, path_)) {
3769 MYLOGE("Could not save stats on %s\n", path_.c_str());
3770 }
3771}
3772
3773int32_t Progress::Get() const {
3774 return progress_;
3775}
3776
3777bool Progress::Inc(int32_t delta_sec) {
3778 bool changed = false;
3779 if (delta_sec >= 0) {
3780 progress_ += delta_sec;
3781 if (progress_ > max_) {
3782 int32_t old_max = max_;
3783 max_ = floor((float)progress_ * growth_factor_);
3784 MYLOGD("Adjusting max progress from %d to %d\n", old_max, max_);
3785 changed = true;
3786 }
3787 }
3788 return changed;
3789}
3790
3791int32_t Progress::GetMax() const {
3792 return max_;
3793}
3794
3795int32_t Progress::GetInitialMax() const {
3796 return initial_max_;
3797}
3798
3799void Progress::Dump(int fd, const std::string& prefix) const {
3800 const char* pr = prefix.c_str();
3801 dprintf(fd, "%sprogress: %d\n", pr, progress_);
3802 dprintf(fd, "%smax: %d\n", pr, max_);
3803 dprintf(fd, "%sinitial_max: %d\n", pr, initial_max_);
3804 dprintf(fd, "%sgrowth_factor: %0.2f\n", pr, growth_factor_);
3805 dprintf(fd, "%spath: %s\n", pr, path_.c_str());
3806 dprintf(fd, "%sn_runs: %d\n", pr, n_runs_);
3807 dprintf(fd, "%saverage_max: %d\n", pr, average_max_);
3808}
3809
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003810std::string Dumpstate::GetPath(const std::string& suffix) const {
3811 return GetPath(bugreport_internal_dir_, suffix);
3812}
3813
3814std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
3815 return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
3816 name_.c_str(), suffix.c_str());
3817}
3818
3819void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
3820 progress_ = std::move(progress);
3821}
3822
3823void for_each_userid(void (*func)(int), const char *header) {
3824 std::string title = header == nullptr ? "for_each_userid" : android::base::StringPrintf(
3825 "for_each_userid(%s)", header);
3826 DurationReporter duration_reporter(title);
3827 if (PropertiesHelper::IsDryRun()) return;
3828
3829 DIR *d;
3830 struct dirent *de;
3831
3832 if (header) printf("\n------ %s ------\n", header);
3833 func(0);
3834
3835 if (!(d = opendir("/data/system/users"))) {
3836 printf("Failed to open /data/system/users (%s)\n", strerror(errno));
3837 return;
3838 }
3839
3840 while ((de = readdir(d))) {
3841 int userid;
3842 if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
3843 continue;
3844 }
3845 func(userid);
3846 }
3847
3848 closedir(d);
3849}
3850
3851static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
3852 DIR *d;
3853 struct dirent *de;
3854
3855 if (!(d = opendir("/proc"))) {
3856 printf("Failed to open /proc (%s)\n", strerror(errno));
3857 return;
3858 }
3859
3860 if (header) printf("\n------ %s ------\n", header);
3861 while ((de = readdir(d))) {
3862 if (ds.IsUserConsentDenied()) {
3863 MYLOGE(
3864 "Returning early because user denied consent to share bugreport with calling app.");
3865 closedir(d);
3866 return;
3867 }
3868 int pid;
3869 int fd;
3870 char cmdpath[255];
3871 char cmdline[255];
3872
3873 if (!(pid = atoi(de->d_name))) {
3874 continue;
3875 }
3876
3877 memset(cmdline, 0, sizeof(cmdline));
3878
3879 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
3880 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3881 TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
3882 close(fd);
3883 if (cmdline[0]) {
3884 helper(pid, cmdline, arg);
3885 continue;
3886 }
3887 }
3888
3889 // if no cmdline, a kernel thread has comm
3890 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
3891 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3892 TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
3893 close(fd);
3894 if (cmdline[1]) {
3895 cmdline[0] = '[';
3896 size_t len = strcspn(cmdline, "\f\b\r\n");
3897 cmdline[len] = ']';
3898 cmdline[len+1] = '\0';
3899 }
3900 }
3901 if (!cmdline[0]) {
3902 strcpy(cmdline, "N/A");
3903 }
3904 helper(pid, cmdline, arg);
3905 }
3906
3907 closedir(d);
3908}
3909
3910static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
3911 for_each_pid_func *func = (for_each_pid_func*) arg;
3912 func(pid, cmdline);
3913}
3914
3915void for_each_pid(for_each_pid_func func, const char *header) {
3916 std::string title = header == nullptr ? "for_each_pid"
3917 : android::base::StringPrintf("for_each_pid(%s)", header);
3918 DurationReporter duration_reporter(title);
3919 if (PropertiesHelper::IsDryRun()) return;
3920
3921 __for_each_pid(for_each_pid_helper, header, (void *) func);
3922}
3923
3924static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
3925 DIR *d;
3926 struct dirent *de;
3927 char taskpath[255];
3928 for_each_tid_func *func = (for_each_tid_func *) arg;
3929
3930 snprintf(taskpath, sizeof(taskpath), "/proc/%d/task", pid);
3931
3932 if (!(d = opendir(taskpath))) {
3933 printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
3934 return;
3935 }
3936
3937 func(pid, pid, cmdline);
3938
3939 while ((de = readdir(d))) {
3940 if (ds.IsUserConsentDenied()) {
3941 MYLOGE(
3942 "Returning early because user denied consent to share bugreport with calling app.");
3943 closedir(d);
3944 return;
3945 }
3946 int tid;
3947 int fd;
3948 char commpath[255];
3949 char comm[255];
3950
3951 if (!(tid = atoi(de->d_name))) {
3952 continue;
3953 }
3954
3955 if (tid == pid)
3956 continue;
3957
3958 snprintf(commpath, sizeof(commpath), "/proc/%d/comm", tid);
3959 memset(comm, 0, sizeof(comm));
3960 if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
3961 strcpy(comm, "N/A");
3962 } else {
3963 char *c;
3964 TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
3965 close(fd);
3966
3967 c = strrchr(comm, '\n');
3968 if (c) {
3969 *c = '\0';
3970 }
3971 }
3972 func(pid, tid, comm);
3973 }
3974
3975 closedir(d);
3976}
3977
3978void for_each_tid(for_each_tid_func func, const char *header) {
3979 std::string title = header == nullptr ? "for_each_tid"
3980 : android::base::StringPrintf("for_each_tid(%s)", header);
3981 DurationReporter duration_reporter(title);
3982
3983 if (PropertiesHelper::IsDryRun()) return;
3984
3985 __for_each_pid(for_each_tid_helper, header, (void *) func);
3986}
3987
3988void show_wchan(int pid, int tid, const char *name) {
3989 if (PropertiesHelper::IsDryRun()) return;
3990
3991 char path[255];
3992 char buffer[255];
3993 int fd, ret, save_errno;
3994 char name_buffer[255];
3995
3996 memset(buffer, 0, sizeof(buffer));
3997
3998 snprintf(path, sizeof(path), "/proc/%d/wchan", tid);
3999 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
4000 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
4001 return;
4002 }
4003
4004 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
4005 save_errno = errno;
4006 close(fd);
4007
4008 if (ret < 0) {
4009 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
4010 return;
4011 }
4012
4013 snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
4014 pid == tid ? 0 : 3, "", name);
4015
4016 printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
4017
4018 return;
4019}
4020
4021// print time in centiseconds
4022static void snprcent(char *buffer, size_t len, size_t spc,
4023 unsigned long long time) {
4024 static long hz; // cache discovered hz
4025
4026 if (hz <= 0) {
4027 hz = sysconf(_SC_CLK_TCK);
4028 if (hz <= 0) {
4029 hz = 1000;
4030 }
4031 }
4032
4033 // convert to centiseconds
4034 time = (time * 100 + (hz / 2)) / hz;
4035
4036 char str[16];
4037
4038 snprintf(str, sizeof(str), " %llu.%02u",
4039 time / 100, (unsigned)(time % 100));
4040 size_t offset = strlen(buffer);
4041 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
4042 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
4043}
4044
4045// print permille as a percent
4046static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
4047 char str[16];
4048
4049 snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
4050 size_t offset = strlen(buffer);
4051 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
4052 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
4053}
4054
4055void show_showtime(int pid, const char *name) {
4056 if (PropertiesHelper::IsDryRun()) return;
4057
4058 char path[255];
4059 char buffer[1023];
4060 int fd, ret, save_errno;
4061
4062 memset(buffer, 0, sizeof(buffer));
4063
4064 snprintf(path, sizeof(path), "/proc/%d/stat", pid);
4065 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
4066 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
4067 return;
4068 }
4069
4070 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
4071 save_errno = errno;
4072 close(fd);
4073
4074 if (ret < 0) {
4075 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
4076 return;
4077 }
4078
4079 // field 14 is utime
4080 // field 15 is stime
4081 // field 42 is iotime
4082 unsigned long long utime = 0, stime = 0, iotime = 0;
4083 if (sscanf(buffer,
4084 "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
4085 "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
4086 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
4087 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
4088 &utime, &stime, &iotime) != 3) {
4089 return;
4090 }
4091
4092 unsigned long long total = utime + stime;
4093 if (!total) {
4094 return;
4095 }
4096
4097 unsigned permille = (iotime * 1000 + (total / 2)) / total;
4098 if (permille > 1000) {
4099 permille = 1000;
4100 }
4101
4102 // try to beautify and stabilize columns at <80 characters
4103 snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
4104 if ((name[0] != '[') || utime) {
4105 snprcent(buffer, sizeof(buffer), 57, utime);
4106 }
4107 snprcent(buffer, sizeof(buffer), 65, stime);
4108 if ((name[0] != '[') || iotime) {
4109 snprcent(buffer, sizeof(buffer), 73, iotime);
4110 }
4111 if (iotime) {
4112 snprdec(buffer, sizeof(buffer), 79, permille);
4113 }
4114 puts(buffer); // adds a trailing newline
4115
4116 return;
4117}
4118
4119void do_dmesg() {
4120 const char *title = "KERNEL LOG (dmesg)";
4121 DurationReporter duration_reporter(title);
4122 printf("------ %s ------\n", title);
4123
4124 if (PropertiesHelper::IsDryRun()) return;
4125
4126 /* Get size of kernel buffer */
4127 int size = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
4128 if (size <= 0) {
4129 printf("Unexpected klogctl return value: %d\n\n", size);
4130 return;
4131 }
4132 char *buf = (char *) malloc(size + 1);
4133 if (buf == nullptr) {
4134 printf("memory allocation failed\n\n");
4135 return;
4136 }
4137 int retval = klogctl(KLOG_READ_ALL, buf, size);
4138 if (retval < 0) {
4139 printf("klogctl failure\n\n");
4140 free(buf);
4141 return;
4142 }
4143 buf[retval] = '\0';
4144 printf("%s\n\n", buf);
4145 free(buf);
4146 return;
4147}
4148
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004149int Dumpstate::DumpFile(const std::string& title, const std::string& path) {
4150 DurationReporter duration_reporter(title);
4151
4152 int status = DumpFileToFd(STDOUT_FILENO, title, path);
4153
4154 UpdateProgress(WEIGHT_FILE);
4155
4156 return status;
4157}
4158
4159int read_file_as_long(const char *path, long int *output) {
4160 int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
4161 if (fd < 0) {
4162 int err = errno;
4163 MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
4164 return -1;
4165 }
4166 char buffer[50];
4167 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
4168 if (bytes_read == -1) {
4169 MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
4170 return -2;
4171 }
4172 if (bytes_read == 0) {
4173 MYLOGE("File %s is empty\n", path);
4174 return -3;
4175 }
4176 *output = atoi(buffer);
4177 return 0;
4178}
4179
4180/* calls skip to gate calling dump_from_fd recursively
4181 * in the specified directory. dump_from_fd defaults to
4182 * dump_file_from_fd above when set to NULL. skip defaults
4183 * to false when set to NULL. dump_from_fd will always be
4184 * called with title NULL.
4185 */
4186int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
4187 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4188 DurationReporter duration_reporter(title);
4189 DIR *dirp;
4190 struct dirent *d;
4191 char *newpath = nullptr;
4192 const char *slash = "/";
4193 int retval = 0;
4194
4195 if (!title.empty()) {
4196 printf("------ %s (%s) ------\n", title.c_str(), dir);
4197 }
4198 if (PropertiesHelper::IsDryRun()) return 0;
4199
4200 if (dir[strlen(dir) - 1] == '/') {
4201 ++slash;
4202 }
4203 dirp = opendir(dir);
4204 if (dirp == nullptr) {
4205 retval = -errno;
4206 MYLOGE("%s: %s\n", dir, strerror(errno));
4207 return retval;
4208 }
4209
4210 if (!dump_from_fd) {
4211 dump_from_fd = dump_file_from_fd;
4212 }
4213 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4214 if ((d->d_name[0] == '.')
4215 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4216 || (d->d_name[1] == '\0'))) {
4217 continue;
4218 }
4219 asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
4220 (d->d_type == DT_DIR) ? "/" : "");
4221 if (!newpath) {
4222 retval = -errno;
4223 continue;
4224 }
4225 if (skip && (*skip)(newpath)) {
4226 continue;
4227 }
4228 if (d->d_type == DT_DIR) {
4229 int ret = dump_files("", newpath, skip, dump_from_fd);
4230 if (ret < 0) {
4231 retval = ret;
4232 }
4233 continue;
4234 }
4235 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
4236 if (fd.get() < 0) {
4237 retval = -1;
4238 printf("*** %s: %s\n", newpath, strerror(errno));
4239 continue;
4240 }
4241 (*dump_from_fd)(nullptr, newpath, fd.get());
4242 }
4243 closedir(dirp);
4244 if (!title.empty()) {
4245 printf("\n");
4246 }
4247 return retval;
4248}
4249
4250/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
4251 * it's possible to avoid issues where opening the file itself can get
4252 * stuck.
4253 */
4254int dump_file_from_fd(const char *title, const char *path, int fd) {
4255 if (PropertiesHelper::IsDryRun()) return 0;
4256
4257 int flags = fcntl(fd, F_GETFL);
4258 if (flags == -1) {
4259 printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
4260 return -1;
4261 } else if (!(flags & O_NONBLOCK)) {
4262 printf("*** %s: fd must have O_NONBLOCK set.\n", path);
4263 return -1;
4264 }
4265 return DumpFileFromFdToFd(title, path, fd, STDOUT_FILENO, PropertiesHelper::IsDryRun());
4266}
4267
4268int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004269 const CommandOptions& options, bool verbose_duration, int out_fd) {
4270 DurationReporter duration_reporter(title, false /* logcat_only */,
4271 verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004272
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004273 int status = RunCommandToFd(out_fd, title, full_command, options);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004274
4275 /* TODO: for now we're simplifying the progress calculation by using the
4276 * timeout as the weight. It's a good approximation for most cases, except when calling dumpsys,
4277 * where its weight should be much higher proportionally to its timeout.
4278 * Ideally, it should use a options.EstimatedDuration() instead...*/
4279 UpdateProgress(options.Timeout());
4280
4281 return status;
4282}
4283
4284void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
Rhed Jaoe017f982020-07-21 17:58:41 +08004285 const CommandOptions& options, long dumpsysTimeoutMs, int out_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004286 long timeout_ms = dumpsysTimeoutMs > 0 ? dumpsysTimeoutMs : options.TimeoutInMs();
4287 std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-T", std::to_string(timeout_ms)};
4288 dumpsys.insert(dumpsys.end(), dumpsys_args.begin(), dumpsys_args.end());
Rhed Jaoe017f982020-07-21 17:58:41 +08004289 RunCommand(title, dumpsys, options, false, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004290}
4291
Dieter Hsu105ad0c2020-09-29 15:23:33 +08004292static int open_socket(const char* service) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004293 int s = android_get_control_socket(service);
4294 if (s < 0) {
4295 MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
4296 return -1;
4297 }
4298 fcntl(s, F_SETFD, FD_CLOEXEC);
4299
4300 // Set backlog to 0 to make sure that queue size will be minimum.
4301 // In Linux, because the minimum queue will be 1, connect() will be blocked
4302 // if the other clients already called connect() and the connection request was not accepted.
4303 if (listen(s, 0) < 0) {
4304 MYLOGE("listen(control socket): %s\n", strerror(errno));
4305 return -1;
4306 }
4307
4308 struct sockaddr addr;
4309 socklen_t alen = sizeof(addr);
Abhijeet Kaur2113cae2019-09-13 09:24:15 +01004310 int fd = accept4(s, &addr, &alen, SOCK_CLOEXEC);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004311
4312 // Close socket just after accept(), to make sure that connect() by client will get error
4313 // when the socket is used by the other services.
4314 // There is still a race condition possibility between accept and close, but there is no way
4315 // to close-on-accept atomically.
4316 // See detail; b/123306389#comment25
4317 close(s);
4318
4319 if (fd < 0) {
4320 MYLOGE("accept(control socket): %s\n", strerror(errno));
4321 return -1;
4322 }
4323
4324 return fd;
4325}
4326
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004327// TODO: should call is_valid_output_file and/or be merged into it.
4328void create_parent_dirs(const char *path) {
4329 char *chp = const_cast<char *> (path);
4330
4331 /* skip initial slash */
4332 if (chp[0] == '/')
4333 chp++;
4334
4335 /* create leading directories, if necessary */
4336 struct stat dir_stat;
4337 while (chp && chp[0]) {
4338 chp = strchr(chp, '/');
4339 if (chp) {
4340 *chp = 0;
4341 if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
4342 MYLOGI("Creating directory %s\n", path);
4343 if (mkdir(path, 0770)) { /* drwxrwx--- */
4344 MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
4345 } else if (chown(path, AID_SHELL, AID_SHELL)) {
4346 MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
4347 }
4348 }
4349 *chp++ = '/';
4350 }
4351 }
4352}
4353
4354bool _redirect_to_file(FILE* redirect, char* path, int truncate_flag) {
4355 create_parent_dirs(path);
4356
4357 int fd = TEMP_FAILURE_RETRY(open(path,
4358 O_WRONLY | O_CREAT | truncate_flag | O_CLOEXEC | O_NOFOLLOW,
4359 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
4360 if (fd < 0) {
4361 MYLOGE("%s: %s\n", path, strerror(errno));
4362 return false;
4363 }
4364
4365 TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
4366 close(fd);
4367 return true;
4368}
4369
4370bool redirect_to_file(FILE* redirect, char* path) {
4371 return _redirect_to_file(redirect, path, O_TRUNC);
4372}
4373
4374bool redirect_to_existing_file(FILE* redirect, char* path) {
4375 return _redirect_to_file(redirect, path, O_APPEND);
4376}
4377
4378void dump_route_tables() {
4379 DurationReporter duration_reporter("DUMP ROUTE TABLES");
4380 if (PropertiesHelper::IsDryRun()) return;
4381 const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
4382 ds.DumpFile("RT_TABLES", RT_TABLES_PATH);
4383 FILE* fp = fopen(RT_TABLES_PATH, "re");
4384 if (!fp) {
4385 printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
4386 return;
4387 }
4388 char table[16];
4389 // Each line has an integer (the table number), a space, and a string (the table name). We only
4390 // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
4391 // Add a fixed max limit so this doesn't go awry.
4392 for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
4393 RunCommand("ROUTE TABLE IPv4", {"ip", "-4", "route", "show", "table", table});
4394 RunCommand("ROUTE TABLE IPv6", {"ip", "-6", "route", "show", "table", table});
4395 }
4396 fclose(fp);
4397}
4398
Li Li830179f2022-01-04 12:53:29 -08004399void dump_frozen_cgroupfs(const char *dir, int level,
4400 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4401 DIR *dirp;
4402 struct dirent *d;
4403 char *newpath = nullptr;
4404
4405 dirp = opendir(dir);
4406 if (dirp == nullptr) {
4407 MYLOGE("%s: %s\n", dir, strerror(errno));
4408 return;
4409 }
4410
4411 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4412 if ((d->d_name[0] == '.')
4413 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4414 || (d->d_name[1] == '\0'))) {
4415 continue;
4416 }
4417 if (d->d_type == DT_DIR) {
4418 asprintf(&newpath, "%s/%s/", dir, d->d_name);
4419 if (!newpath) {
4420 continue;
4421 }
4422 if (level == 0 && !strncmp(d->d_name, "uid_", 4)) {
4423 dump_frozen_cgroupfs(newpath, 1, dump_from_fd);
4424 } else if (level == 1 && !strncmp(d->d_name, "pid_", 4)) {
4425 char *freezer = nullptr;
4426 asprintf(&freezer, "%s/%s", newpath, "cgroup.freeze");
4427 if (freezer) {
4428 FILE* fp = fopen(freezer, "r");
4429 if (fp != NULL) {
4430 int frozen;
4431 fscanf(fp, "%d", &frozen);
4432 if (frozen > 0) {
4433 dump_files("", newpath, skip_none, dump_from_fd);
4434 }
4435 fclose(fp);
4436 }
4437 free(freezer);
4438 }
4439 }
4440 }
4441 }
4442 closedir(dirp);
4443}
4444
4445void dump_frozen_cgroupfs() {
Li Li830179f2022-01-04 12:53:29 -08004446 MYLOGD("Adding frozen processes from %s\n", CGROUPFS_DIR);
4447 DurationReporter duration_reporter("FROZEN CGROUPFS");
4448 if (PropertiesHelper::IsDryRun()) return;
4449 dump_frozen_cgroupfs(CGROUPFS_DIR, 0, _add_file_from_fd);
4450}
4451
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004452void Dumpstate::UpdateProgress(int32_t delta_sec) {
4453 if (progress_ == nullptr) {
4454 MYLOGE("UpdateProgress: progress_ not set\n");
4455 return;
4456 }
Rhed Jaobf63d8a2020-07-21 15:42:55 +08004457 // This function updates progress related members of the dumpstate and reports
4458 // progress percentage to the bugreport client. Since it could be called by
4459 // different dump tasks at the same time if the parallel run is enabled, a
4460 // mutex lock is necessary here to synchronize the call.
4461 std::lock_guard<std::recursive_mutex> lock(mutex_);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004462
4463 // Always update progess so stats can be tuned...
Nandana Dutt402a8392019-06-14 14:25:13 +01004464 progress_->Inc(delta_sec);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004465
4466 // ...but only notifiy listeners when necessary.
4467 if (!options_->do_progress_updates) return;
4468
4469 int progress = progress_->Get();
4470 int max = progress_->GetMax();
Nandana Dutt402a8392019-06-14 14:25:13 +01004471 int percent = 100 * progress / max;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004472
Nandana Dutt402a8392019-06-14 14:25:13 +01004473 if (last_reported_percent_progress_ > 0 && percent <= last_reported_percent_progress_) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004474 return;
4475 }
Nandana Dutt402a8392019-06-14 14:25:13 +01004476 last_reported_percent_progress_ = percent;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004477
4478 if (control_socket_fd_ >= 0) {
4479 dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
4480 fsync(control_socket_fd_);
4481 }
4482
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004483 if (listener_ != nullptr) {
Nandana Dutt235c6672019-11-14 15:22:32 +00004484 if (percent % 10 == 0) {
4485 // We don't want to spam logcat, so only log multiples of 10.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004486 MYLOGD("Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004487 } else {
4488 // stderr is ignored on normal invocations, but useful when calling
4489 // /system/bin/dumpstate directly for debuggging.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004490 fprintf(stderr, "Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004491 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004492
4493 listener_->onProgress(percent);
4494 }
4495}
4496
4497void Dumpstate::TakeScreenshot(const std::string& path) {
4498 const std::string& real_path = path.empty() ? screenshot_path_ : path;
4499 int status =
4500 RunCommand("", {"/system/bin/screencap", "-p", real_path},
4501 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
4502 if (status == 0) {
4503 MYLOGD("Screenshot saved on %s\n", real_path.c_str());
4504 } else {
4505 MYLOGE("Failed to take screenshot on %s\n", real_path.c_str());
4506 }
Paul Chang0d2aad72020-02-13 20:04:03 +08004507 if (listener_ != nullptr) {
4508 // Show a visual indication to indicate screenshot is taken via
4509 // IDumpstateListener.onScreenshotTaken()
4510 listener_->onScreenshotTaken(status == 0);
4511 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004512}
4513
4514bool is_dir(const char* pathname) {
4515 struct stat info;
4516 if (stat(pathname, &info) == -1) {
4517 return false;
4518 }
4519 return S_ISDIR(info.st_mode);
4520}
4521
4522time_t get_mtime(int fd, time_t default_mtime) {
4523 struct stat info;
4524 if (fstat(fd, &info) == -1) {
4525 return default_mtime;
4526 }
4527 return info.st_mtime;
4528}