blob: 33f6d38cc6b7be363e76a862b284aa53a4b36fe7 [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>
Felipe Leme96c2bbb2016-09-26 09:21:21 -070062#include <android-base/file.h>
63#include <android-base/properties.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070064#include <android-base/scopeguard.h>
Elliott Hughes9dc117c2015-12-07 14:21:50 -080065#include <android-base/stringprintf.h>
Naveen Kalla058e1e82016-10-19 21:38:44 -070066#include <android-base/strings.h>
Andreas Gampeaff68432016-07-18 18:01:27 -070067#include <android-base/unique_fd.h>
Kedar Chitnis9fd8c052021-11-16 09:09:22 +000068#include <android/binder_manager.h>
69#include <android/binder_process.h>
Nikita Ioffea325a572019-05-16 19:49:47 +010070#include <android/content/pm/IPackageManagerNative.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080071#include <android/hardware/dumpstate/1.0/IDumpstateDevice.h>
Hunter Knepshield8540faf2020-02-04 19:47:20 -080072#include <android/hardware/dumpstate/1.1/IDumpstateDevice.h>
73#include <android/hardware/dumpstate/1.1/types.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080074#include <android/hidl/manager/1.0/IServiceManager.h>
Nandana Duttd2f5f082019-01-18 17:13:52 +000075#include <android/os/IIncidentCompanion.h>
Nikita Ioffea325a572019-05-16 19:49:47 +010076#include <binder/IServiceManager.h>
Nikhil Kumar28ce35e2023-01-10 14:32:44 +000077#include <cutils/multiuser.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080078#include <cutils/native_handle.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070079#include <cutils/properties.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010080#include <cutils/sockets.h>
Kevin Jeon2c02e8e2022-07-07 21:45:17 +000081#include <cutils/trace.h>
Nandana Duttfaafd522019-03-11 09:23:09 +000082#include <debuggerd/client.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080083#include <dumpsys.h>
Nandana Duttfaafd522019-03-11 09:23:09 +000084#include <dumputils/dump_utils.h>
Sahana Raof35ed432019-07-12 10:47:52 +010085#include <hardware_legacy/power.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080086#include <hidl/ServiceManagement.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010087#include <log/log.h>
Tom Cherryf4472f32020-08-05 09:31:17 -070088#include <log/log_read.h>
Felipe Leme75876a22016-10-27 16:31:27 -070089#include <openssl/sha.h>
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070090#include <private/android_filesystem_config.h>
91#include <private/android_logger.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080092#include <serviceutils/PriorityDumper.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070093#include <utils/StrongPointer.h>
Devin Moore8df81bb2022-06-08 22:47:02 +000094#include <vintf/VintfObject.h>
Felipe Lemef0292972016-11-22 13:57:05 -080095#include "DumpstateInternal.h"
Felipe Leme75876a22016-10-27 16:31:27 -070096#include "DumpstateService.h"
Colin Crossf45fa6b2012-03-26 12:38:26 -070097#include "dumpstate.h"
Felipe Leme6e01fa62015-11-11 19:35:14 -080098
Kedar Chitnis9fd8c052021-11-16 09:09:22 +000099namespace dumpstate_hal_hidl_1_0 = android::hardware::dumpstate::V1_0;
100namespace dumpstate_hal_hidl = android::hardware::dumpstate::V1_1;
101namespace dumpstate_hal_aidl = aidl::android::hardware::dumpstate;
102
Vishnu Naire97d6122018-01-18 13:58:56 -0800103using ::std::literals::chrono_literals::operator""ms;
104using ::std::literals::chrono_literals::operator""s;
Rhed Jao5377d792020-07-16 17:37:39 +0800105using ::std::placeholders::_1;
Steven Morelandcb7ef822016-11-29 13:20:37 -0800106
Felipe Leme47e9be22016-12-21 15:37:07 -0800107// TODO: remove once moved to namespace
Vishnu Naire97d6122018-01-18 13:58:56 -0800108using android::defaultServiceManager;
109using android::Dumpsys;
110using android::INVALID_OPERATION;
111using android::IServiceManager;
112using android::OK;
113using android::sp;
114using android::status_t;
115using android::String16;
116using android::String8;
117using android::TIMED_OUT;
118using android::UNKNOWN_ERROR;
119using android::Vector;
Nandana Dutt979388e2018-11-30 16:48:55 +0000120using android::base::StringPrintf;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000121using android::os::IDumpstateListener;
Felipe Leme47e9be22016-12-21 15:37:07 -0800122using android::os::dumpstate::CommandOptions;
123using android::os::dumpstate::DumpFileToFd;
Rhed Jao5377d792020-07-16 17:37:39 +0800124using android::os::dumpstate::DumpPool;
Vishnu Naire97d6122018-01-18 13:58:56 -0800125using android::os::dumpstate::PropertiesHelper;
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800126using android::os::dumpstate::TaskQueue;
Chris Morinbc223142022-02-04 14:17:11 -0800127using android::os::dumpstate::WaitForTask;
Felipe Leme47e9be22016-12-21 15:37:07 -0800128
Abhijeet Kaurcf234e82019-07-01 14:53:55 +0100129// Keep in sync with
130// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
131static const int TRACE_DUMP_TIMEOUT_MS = 10000; // 10 seconds
132
133/* Most simple commands have 10 as timeout, so 5 is a good estimate */
134static const int32_t WEIGHT_FILE = 5;
135
136// TODO: temporary variables and functions used during C++ refactoring
137static Dumpstate& ds = Dumpstate::GetInstance();
138static int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Nandana Dutt8d945c02019-08-14 13:30:07 +0100139 const CommandOptions& options = CommandOptions::DEFAULT,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800140 bool verbose_duration = false, int out_fd = STDOUT_FILENO) {
141 return ds.RunCommand(title, full_command, options, verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +0100142}
143
144// Reasonable value for max stats.
145static const int STATS_MAX_N_RUNS = 1000;
146static const long STATS_MAX_AVERAGE = 100000;
147
148CommandOptions Dumpstate::DEFAULT_DUMPSYS = CommandOptions::WithTimeout(30).Build();
149
Nandana Duttd2f5f082019-01-18 17:13:52 +0000150typedef Dumpstate::ConsentCallback::ConsentResult UserConsentResult;
151
Colin Crossf45fa6b2012-03-26 12:38:26 -0700152/* read before root is shed */
153static char cmdline_buf[16384] = "(unknown)";
Yi Kong19d5c002018-07-20 13:39:55 -0700154static const char *dump_traces_path = nullptr;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000155static const uint64_t USER_CONSENT_TIMEOUT_MS = 30 * 1000;
Hunter Knepshield70610fa2020-01-03 15:27:33 -0800156// Because telephony reports are significantly faster to collect (< 10 seconds vs. > 2 minutes),
157// it's often the case that they time out far too quickly for consent with such a hefty dialog for
158// the user to read. For telephony reports only, we increase the default timeout to 2 minutes to
159// roughly match full reports' durations.
160static const uint64_t TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS = 2 * 60 * 1000;
Colin Crossf45fa6b2012-03-26 12:38:26 -0700161
Felipe Leme1d486fe2016-10-14 18:06:47 -0700162// TODO: variables and functions below should be part of dumpstate object
163
Felipe Leme635ca312016-01-05 14:23:02 -0800164static std::set<std::string> mount_points;
165void add_mountinfo();
Felipe Leme78f2c862015-12-21 09:55:22 -0800166
Todd Poynor2a83daa2013-11-22 15:44:22 -0800167#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
Mark Salyzyn7d0a7622016-06-24 14:06:15 -0700168#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
Wei Wang509bb5d2017-06-09 14:42:12 -0700169#define BLK_DEV_SYS_DIR "/sys/block"
Todd Poynor2a83daa2013-11-22 15:44:22 -0800170
Felipe Lemee82a27d2016-01-05 13:35:44 -0800171#define RECOVERY_DIR "/cache/recovery"
Mark Salyzynd6ab0112016-03-25 12:56:39 -0700172#define RECOVERY_DATA_DIR "/data/misc/recovery"
Tianjie Xu75d53362018-04-11 16:42:28 -0700173#define UPDATE_ENGINE_LOG_DIR "/data/misc/update_engine_log"
Kelvin Zhang6eaa0f92022-09-12 09:29:19 -0700174#define UPDATE_ENGINE_PREF_DIR "/data/misc/update_engine/prefs"
Mark Salyzyn4d42dea2016-04-01 10:03:14 -0700175#define LOGPERSIST_DATA_DIR "/data/misc/logd"
Jerry Changa1df8a92020-01-02 16:03:39 +0800176#define PREREBOOT_DATA_DIR "/data/misc/prereboot"
David Brazdild2991962016-06-03 14:40:44 +0100177#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
178#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
Benedict Wong8f9d8a42019-01-03 16:19:38 -0800179#define XFRM_STAT_PROC_FILE "/proc/net/xfrm_stat"
Erik Kline08165202016-05-30 11:55:44 +0900180#define WLUTIL "/vendor/xbin/wlutil"
Vishnu Nair36b4cdb2017-11-17 10:27:05 -0800181#define WMTRACE_DATA_DIR "/data/misc/wmtrace"
Yifan Hong3945e1b2019-10-29 12:59:23 -0700182#define OTA_METADATA_DIR "/metadata/ota"
Yifan Hong0efa7972020-02-03 16:45:02 -0800183#define SNAPSHOTCTL_LOG_DIR "/data/misc/snapshotctl_log"
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +0900184#define LINKERCONFIG_DIR "/linkerconfig"
Calin Juravlef84d3692020-04-28 15:31:12 -0700185#define PACKAGE_DEX_USE_LIST "/data/system/package-dex-usage.list"
Primiano Tuccifaaaafb2021-01-14 12:26:29 +0000186#define SYSTEM_TRACE_SNAPSHOT "/data/misc/perfetto-traces/bugreport/systrace.pftrace"
Li Li2eedd412021-06-30 15:11:53 -0700187#define CGROUPFS_DIR "/sys/fs/cgroup"
Mårten Kongstad60195a72022-09-20 14:14:20 +0200188#define SDK_EXT_INFO "/apex/com.android.sdkext/bin/derive_sdk"
Jeff Sharkey9df29d52023-02-06 14:26:30 -0700189#define DROPBOX_DIR "/data/system/dropbox"
Mårten Kongstad5ad813f2023-09-28 10:09:18 +0200190#define PRINT_FLAGS "/system/bin/printflags"
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700191
Narayan Kamath8f788292017-05-25 13:20:39 +0100192// TODO(narayan): Since this information has to be kept in sync
193// with tombstoned, we should just put it in a common header.
194//
195// File: system/core/debuggerd/tombstoned/tombstoned.cpp
Narayan Kamathbd863722017-06-01 18:50:12 +0100196static const std::string TOMBSTONE_DIR = "/data/tombstones/";
197static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
198static const std::string ANR_DIR = "/data/anr/";
199static const std::string ANR_FILE_PREFIX = "anr_";
Woody Lin20767a92022-11-29 15:50:24 +0800200static const std::string SHUTDOWN_CHECKPOINTS_DIR = "/data/system/shutdown-checkpoints/";
201static const std::string SHUTDOWN_CHECKPOINTS_FILE_PREFIX = "checkpoints-";
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700202
Felipe Lemee844a9d2016-09-21 15:01:39 -0700203// TODO: temporary variables and functions used during C++ refactoring
Nandana Dutt979388e2018-11-30 16:48:55 +0000204
Nandana Dutt5c390032019-03-12 10:52:56 +0000205#define RETURN_IF_USER_DENIED_CONSENT() \
206 if (ds.IsUserConsentDenied()) { \
207 MYLOGE("Returning early as user denied consent to share bugreport with calling app."); \
208 return Dumpstate::RunStatus::USER_CONSENT_DENIED; \
209 }
210
211// Runs func_ptr, but checks user consent before and after running it. Returns USER_CONSENT_DENIED
212// if consent is found to be denied.
213#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(func_ptr, ...) \
214 RETURN_IF_USER_DENIED_CONSENT(); \
215 func_ptr(__VA_ARGS__); \
216 RETURN_IF_USER_DENIED_CONSENT();
217
Rhed Jao5377d792020-07-16 17:37:39 +0800218// Runs func_ptr, and logs a duration report after it's finished.
219#define RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, ...) \
220 { \
221 DurationReporter duration_reporter_in_macro(log_title); \
222 func_ptr(__VA_ARGS__); \
223 }
224
225// Similar with RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK, an additional duration report
226// is output after a slow function is finished.
227#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(log_title, func_ptr, ...) \
228 RETURN_IF_USER_DENIED_CONSENT(); \
229 RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, __VA_ARGS__); \
230 RETURN_IF_USER_DENIED_CONSENT();
231
Chris Morinbc223142022-02-04 14:17:11 -0800232#define WAIT_TASK_WITH_CONSENT_CHECK(future) \
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800233 RETURN_IF_USER_DENIED_CONSENT(); \
Chris Morinbc223142022-02-04 14:17:11 -0800234 WaitForTask(future); \
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800235 RETURN_IF_USER_DENIED_CONSENT();
236
Sahana Raof35ed432019-07-12 10:47:52 +0100237static const char* WAKE_LOCK_NAME = "dumpstate_wakelock";
238
Rhed Jao5377d792020-07-16 17:37:39 +0800239// Names of parallel tasks, they are used for the DumpPool to identify the dump
240// task and the log title of the duration report.
241static const std::string DUMP_TRACES_TASK = "DUMP TRACES";
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800242static const std::string DUMP_INCIDENT_REPORT_TASK = "INCIDENT REPORT";
Aaron Huang24d215d2022-04-27 18:51:16 +0800243static const std::string DUMP_NETSTATS_PROTO_TASK = "DUMP NETSTATS PROTO";
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800244static const std::string DUMP_HALS_TASK = "DUMP HALS";
245static const std::string DUMP_BOARD_TASK = "dumpstate_board()";
Rhed Jaoe017f982020-07-21 17:58:41 +0800246static const std::string DUMP_CHECKINS_TASK = "DUMP CHECKINS";
Kean Mariotti306633e2022-09-05 16:30:47 +0000247static const std::string POST_PROCESS_UI_TRACES_TASK = "POST-PROCESS UI TRACES";
Rhed Jao5377d792020-07-16 17:37:39 +0800248
Nandana Dutt979388e2018-11-30 16:48:55 +0000249namespace android {
250namespace os {
251namespace {
252
253static int Open(std::string path, int flags, mode_t mode = 0) {
254 int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
255 if (fd == -1) {
256 MYLOGE("open(%s, %s)\n", path.c_str(), strerror(errno));
257 }
258 return fd;
259}
260
mhasank2d75c442020-06-11 15:05:25 -0700261static int OpenForWrite(std::string path) {
262 return Open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
263 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
264}
Nandana Dutt979388e2018-11-30 16:48:55 +0000265
266static int OpenForRead(std::string path) {
267 return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
268}
269
270bool CopyFile(int in_fd, int out_fd) {
271 char buf[4096];
272 ssize_t byte_count;
273 while ((byte_count = TEMP_FAILURE_RETRY(read(in_fd, buf, sizeof(buf)))) > 0) {
274 if (!android::base::WriteFully(out_fd, buf, byte_count)) {
275 return false;
276 }
277 }
278 return (byte_count != -1);
279}
280
281static bool CopyFileToFd(const std::string& input_file, int out_fd) {
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000282 MYLOGD("Going to copy file (%s) to %d\n", input_file.c_str(), out_fd);
Nandana Dutt979388e2018-11-30 16:48:55 +0000283
284 // Obtain a handle to the source file.
285 android::base::unique_fd in_fd(OpenForRead(input_file));
286 if (out_fd != -1 && in_fd.get() != -1) {
287 if (CopyFile(in_fd.get(), out_fd)) {
288 return true;
289 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000290 MYLOGE("Failed to copy file: %s\n", strerror(errno));
Nandana Dutt979388e2018-11-30 16:48:55 +0000291 }
292 return false;
293}
294
Nandana Duttd2f5f082019-01-18 17:13:52 +0000295static bool UnlinkAndLogOnError(const std::string& file) {
Nandana Dutt8ae16e62020-03-27 10:20:22 +0000296 if (file.empty()) {
297 return false;
298 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000299 if (unlink(file.c_str())) {
300 MYLOGE("Failed to unlink file (%s): %s\n", file.c_str(), strerror(errno));
Nandana Duttd2f5f082019-01-18 17:13:52 +0000301 return false;
302 }
303 return true;
304}
Nandana Dutt979388e2018-11-30 16:48:55 +0000305
Nikita Ioffea325a572019-05-16 19:49:47 +0100306int64_t GetModuleMetadataVersion() {
307 auto binder = defaultServiceManager()->getService(android::String16("package_native"));
308 if (binder == nullptr) {
309 MYLOGE("Failed to retrieve package_native service");
310 return 0L;
311 }
312 auto package_service = android::interface_cast<content::pm::IPackageManagerNative>(binder);
313 std::string package_name;
314 auto status = package_service->getModuleMetadataPackageName(&package_name);
315 if (!status.isOk()) {
316 MYLOGE("Failed to retrieve module metadata package name: %s", status.toString8().c_str());
317 return 0L;
318 }
Nandana Duttdb379fa2019-10-09 16:54:41 +0100319 MYLOGD("Module metadata package name: %s\n", package_name.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100320 int64_t version_code;
321 status = package_service->getVersionCodeForPackage(android::String16(package_name.c_str()),
322 &version_code);
323 if (!status.isOk()) {
324 MYLOGE("Failed to retrieve module metadata version: %s", status.toString8().c_str());
325 return 0L;
326 }
327 return version_code;
328}
329
mhasank2d75c442020-06-11 15:05:25 -0700330static bool PathExists(const std::string& path) {
331 struct stat sb;
332 return stat(path.c_str(), &sb) == 0;
333}
334
335static bool CopyFileToFile(const std::string& input_file, const std::string& output_file) {
336 if (input_file == output_file) {
337 MYLOGD("Skipping copying bugreport file since the destination is the same (%s)\n",
338 output_file.c_str());
339 return false;
340 }
341 else if (PathExists(output_file)) {
342 MYLOGD("Cannot overwrite an existing file (%s)\n", output_file.c_str());
343 return false;
344 }
345
346 MYLOGD("Going to copy bugreport file (%s) to %s\n", input_file.c_str(), output_file.c_str());
347 android::base::unique_fd out_fd(OpenForWrite(output_file));
348 return CopyFileToFd(input_file, out_fd.get());
349}
350
Nandana Dutt979388e2018-11-30 16:48:55 +0000351} // namespace
352} // namespace os
353} // namespace android
354
Felipe Leme678727a2016-09-21 17:22:11 -0700355static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
Felipe Lemebda15a02016-11-16 17:48:25 -0800356 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
Rhed Jaoe017f982020-07-21 17:58:41 +0800357 long dumpsysTimeoutMs = 0, int out_fd = STDOUT_FILENO) {
358 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs, out_fd);
359}
360static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
361 int out_fd) {
362 return ds.RunDumpsys(title, dumpsysArgs, Dumpstate::DEFAULT_DUMPSYS, 0, out_fd);
Felipe Leme678727a2016-09-21 17:22:11 -0700363}
364static int DumpFile(const std::string& title, const std::string& path) {
365 return ds.DumpFile(title, path);
366}
Felipe Lemee82a27d2016-01-05 13:35:44 -0800367
Felipe Lemee844a9d2016-09-21 15:01:39 -0700368// Relative directory (inside the zip) for all files copied as-is into the bugreport.
369static const std::string ZIP_ROOT_DIR = "FS";
370
Vishnu Naire97d6122018-01-18 13:58:56 -0800371static const std::string kProtoPath = "proto/";
372static const std::string kProtoExt = ".proto";
Jie Song9fbfad02017-06-20 16:29:42 -0700373static const std::string kDumpstateBoardFiles[] = {
374 "dumpstate_board.txt",
Felipe Leme95d6ca52017-08-01 16:35:56 -0700375 "dumpstate_board.bin"
Jie Song9fbfad02017-06-20 16:29:42 -0700376};
377static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
378
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700379static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Lemed071c682016-10-20 16:48:00 -0700380static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700381
Felipe Lemef0292972016-11-22 13:57:05 -0800382static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
383
Narayan Kamath8f788292017-05-25 13:20:39 +0100384/*
Narayan Kamathbd863722017-06-01 18:50:12 +0100385 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
Rhed Jao01dc0c62020-06-03 17:13:30 +0800386 * The returned vector is sorted by the mtimes of the dumps with descending
Chris Morinc2cba7a2022-02-01 17:06:50 -0800387 * order.
Narayan Kamath8f788292017-05-25 13:20:39 +0100388 */
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700389static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
Chris Morinc2cba7a2022-02-01 17:06:50 -0800390 const std::string& file_prefix) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100391 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100392
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700393 if (dump_dir == nullptr) {
394 MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno));
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700395 return std::vector<DumpData>();
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700396 }
397
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700398 std::vector<DumpData> dump_data;
Narayan Kamathbd863722017-06-01 18:50:12 +0100399 struct dirent* entry = nullptr;
400 while ((entry = readdir(dump_dir.get()))) {
401 if (entry->d_type != DT_REG) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100402 continue;
403 }
404
Narayan Kamathbd863722017-06-01 18:50:12 +0100405 const std::string base_name(entry->d_name);
406 if (base_name.find(file_prefix) != 0) {
407 continue;
408 }
409
410 const std::string abs_path = dir_path + base_name;
411 android::base::unique_fd fd(
412 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
413 if (fd == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700414 MYLOGW("Unable to open dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamathbd863722017-06-01 18:50:12 +0100415 break;
416 }
417
418 struct stat st = {};
419 if (fstat(fd, &st) == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700420 MYLOGW("Unable to stat dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamath8f788292017-05-25 13:20:39 +0100421 continue;
422 }
423
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700424 dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700425 }
Rhed Jao01dc0c62020-06-03 17:13:30 +0800426 if (!dump_data.empty()) {
427 std::sort(dump_data.begin(), dump_data.end(),
428 [](const auto& a, const auto& b) { return a.mtime > b.mtime; });
429 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100430
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700431 return dump_data;
Narayan Kamath8f788292017-05-25 13:20:39 +0100432}
433
Narayan Kamathbd863722017-06-01 18:50:12 +0100434static bool AddDumps(const std::vector<DumpData>::const_iterator start,
435 const std::vector<DumpData>::const_iterator end,
436 const char* type_name, const bool add_to_zip) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100437 bool dumped = false;
Narayan Kamathbd863722017-06-01 18:50:12 +0100438 for (auto it = start; it != end; ++it) {
439 const std::string& name = it->name;
440 const int fd = it->fd;
Narayan Kamath8f788292017-05-25 13:20:39 +0100441 dumped = true;
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100442
443 // Seek to the beginning of the file before dumping any data. A given
444 // DumpData entry might be dumped multiple times in the report.
445 //
446 // For example, the most recent ANR entry is dumped to the body of the
447 // main entry and it also shows up as a separate entry in the bugreport
448 // ZIP file.
449 if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) {
450 MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(),
451 strerror(errno));
452 }
453
Chris Morinc2cba7a2022-02-01 17:06:50 -0800454 if (add_to_zip) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800455 if (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd, /* timeout = */ 0ms) != OK) {
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100456 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100457 }
458 } else {
459 dump_file_from_fd(type_name, name.c_str(), fd);
460 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100461 }
462
463 return dumped;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700464}
465
Felipe Leme635ca312016-01-05 14:23:02 -0800466// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700467void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800468 char path[PATH_MAX];
469
470 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
471 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700472 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800473 char linkname[PATH_MAX];
474 ssize_t r = readlink(path, linkname, PATH_MAX);
475 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800476 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800477 return;
478 }
479 linkname[r] = '\0';
480
481 if (mount_points.find(linkname) == mount_points.end()) {
482 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700483 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700484 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
Felipe Leme635ca312016-01-05 14:23:02 -0800485 mount_points.insert(linkname);
486 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800487 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800488 }
489 }
490}
491
492void add_mountinfo() {
Felipe Leme678727a2016-09-21 17:22:11 -0700493 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800494 mount_points.clear();
Felipe Leme46b85da2016-11-21 17:40:45 -0800495 DurationReporter duration_reporter(title, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700496 for_each_pid(do_mountinfo, nullptr);
497 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800498}
499
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700500static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
501{
502 DIR *d;
503 struct dirent *de;
504 char path[PATH_MAX];
505
506 d = opendir(driverpath);
Yi Kong19d5c002018-07-20 13:39:55 -0700507 if (d == nullptr) {
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700508 return;
509 }
510
511 while ((de = readdir(d))) {
512 if (de->d_type != DT_LNK) {
513 continue;
514 }
515 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700516 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700517 }
518
519 closedir(d);
520}
521
Mark Salyzyn326842f2015-04-30 09:49:41 -0700522static bool skip_not_stat(const char *path) {
523 static const char stat[] = "/stat";
524 size_t len = strlen(path);
525 if (path[len - 1] == '/') { /* Directory? */
526 return false;
527 }
528 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
529}
530
Jeff Sharkey9df29d52023-02-06 14:26:30 -0700531static bool skip_wtf_strictmode(const char *path) {
532 if (strstr(path, "_wtf")) {
533 return true;
534 } else if (strstr(path, "_strictmode")) {
535 return true;
536 }
537 return false;
538}
539
Felipe Leme4c2d6632016-09-28 14:32:00 -0700540static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800541 return false;
542}
543
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700544unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700545
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800546//
547// stat offsets
548// Name units description
549// ---- ----- -----------
550// read I/Os requests number of read I/Os processed
551#define __STAT_READ_IOS 0
552// read merges requests number of read I/Os merged with in-queue I/O
553#define __STAT_READ_MERGES 1
554// read sectors sectors number of sectors read
555#define __STAT_READ_SECTORS 2
556// read ticks milliseconds total wait time for read requests
557#define __STAT_READ_TICKS 3
558// write I/Os requests number of write I/Os processed
559#define __STAT_WRITE_IOS 4
560// write merges requests number of write I/Os merged with in-queue I/O
561#define __STAT_WRITE_MERGES 5
562// write sectors sectors number of sectors written
563#define __STAT_WRITE_SECTORS 6
564// write ticks milliseconds total wait time for write requests
565#define __STAT_WRITE_TICKS 7
566// in_flight requests number of I/Os currently in flight
567#define __STAT_IN_FLIGHT 8
568// io_ticks milliseconds total time this block device has been active
569#define __STAT_IO_TICKS 9
570// time_in_queue milliseconds total wait time for all requests
571#define __STAT_IN_QUEUE 10
572#define __STAT_NUMBER_FIELD 11
573//
574// read I/Os, write I/Os
575// =====================
576//
577// These values increment when an I/O request completes.
578//
579// read merges, write merges
580// =========================
581//
582// These values increment when an I/O request is merged with an
583// already-queued I/O request.
584//
585// read sectors, write sectors
586// ===========================
587//
588// These values count the number of sectors read from or written to this
589// block device. The "sectors" in question are the standard UNIX 512-byte
590// sectors, not any device- or filesystem-specific block size. The
591// counters are incremented when the I/O completes.
592#define SECTOR_SIZE 512
593//
594// read ticks, write ticks
595// =======================
596//
597// These values count the number of milliseconds that I/O requests have
598// waited on this block device. If there are multiple I/O requests waiting,
599// these values will increase at a rate greater than 1000/second; for
600// example, if 60 read requests wait for an average of 30 ms, the read_ticks
601// field will increase by 60*30 = 1800.
602//
603// in_flight
604// =========
605//
606// This value counts the number of I/O requests that have been issued to
607// the device driver but have not yet completed. It does not include I/O
608// requests that are in the queue but not yet issued to the device driver.
609//
610// io_ticks
611// ========
612//
613// This value counts the number of milliseconds during which the device has
614// had I/O requests queued.
615//
616// time_in_queue
617// =============
618//
619// This value counts the number of milliseconds that I/O requests have waited
620// on this block device. If there are multiple I/O requests waiting, this
621// value will increase as the product of the number of milliseconds times the
622// number of requests waiting (see "read ticks" above for an example).
623#define S_TO_MS 1000
624//
625
Mark Salyzyn326842f2015-04-30 09:49:41 -0700626static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800627 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700628 bool z;
Yi Kong19d5c002018-07-20 13:39:55 -0700629 char *cp, *buffer = nullptr;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700630 size_t i = 0;
Josh Gao7c4258c2018-06-25 13:40:08 -0700631 FILE *fp = fdopen(dup(fd), "rb");
Mark Salyzyn326842f2015-04-30 09:49:41 -0700632 getline(&buffer, &i, fp);
633 fclose(fp);
634 if (!buffer) {
635 return -errno;
636 }
637 i = strlen(buffer);
638 while ((i > 0) && (buffer[i - 1] == '\n')) {
639 buffer[--i] = '\0';
640 }
641 if (!*buffer) {
642 free(buffer);
643 return 0;
644 }
645 z = true;
646 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800647 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700648 if (fields[i] != 0) {
649 z = false;
650 }
651 }
652 if (z) { /* never accessed */
653 free(buffer);
654 return 0;
655 }
656
Wei Wang509bb5d2017-06-09 14:42:12 -0700657 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
658 path += sizeof(BLK_DEV_SYS_DIR) - 1;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700659 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700660
661 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
662 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
663 "W-wait", "in-fli", "activ", "T-wait", path, buffer);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700664 free(buffer);
665
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800666 if (fields[__STAT_IO_TICKS]) {
667 unsigned long read_perf = 0;
668 unsigned long read_ios = 0;
669 if (fields[__STAT_READ_TICKS]) {
670 unsigned long long divisor = fields[__STAT_READ_TICKS]
671 * fields[__STAT_IO_TICKS];
672 read_perf = ((unsigned long long)SECTOR_SIZE
673 * fields[__STAT_READ_SECTORS]
674 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
675 / divisor;
676 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
677 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
678 / divisor;
679 }
680
681 unsigned long write_perf = 0;
682 unsigned long write_ios = 0;
683 if (fields[__STAT_WRITE_TICKS]) {
684 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
685 * fields[__STAT_IO_TICKS];
686 write_perf = ((unsigned long long)SECTOR_SIZE
687 * fields[__STAT_WRITE_SECTORS]
688 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
689 / divisor;
690 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
691 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
692 / divisor;
693 }
694
695 unsigned queue = (fields[__STAT_IN_QUEUE]
696 + (fields[__STAT_IO_TICKS] >> 1))
697 / fields[__STAT_IO_TICKS];
698
699 if (!write_perf && !write_ios) {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700700 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 -0800701 } else {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700702 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 -0800703 read_ios, write_perf, write_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800704 }
705
706 /* bugreport timeout factor adjustment */
707 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
708 worst_write_perf = write_perf;
709 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700710 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700711 return 0;
712}
713
Yao Chenbe3bbc12018-01-17 16:31:10 -0800714static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
715
Tom Cherryf4472f32020-08-05 09:31:17 -0700716// Returns the actual readable size of the given buffer or -1 on error.
717static long logcat_buffer_readable_size(const std::string& buffer) {
718 std::unique_ptr<logger_list, decltype(&android_logger_list_free)> logger_list{
719 android_logger_list_alloc(0, 0, 0), &android_logger_list_free};
720 auto logger = android_logger_open(logger_list.get(), android_name_to_log_id(buffer.c_str()));
721
722 return android_logger_get_log_readable_size(logger);
723}
724
725// Returns timeout in ms to read a list of buffers.
Yao Chenbe3bbc12018-01-17 16:31:10 -0800726static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
727 unsigned long timeout_ms = 0;
728 for (const auto& buffer : buffers) {
Tom Cherryf4472f32020-08-05 09:31:17 -0700729 long readable_size = logcat_buffer_readable_size(buffer);
730 if (readable_size > 0) {
731 // Engineering margin is ten-fold our guess.
732 timeout_ms += 10 * (readable_size + worst_write_perf) / worst_write_perf;
733 }
Yao Chenbe3bbc12018-01-17 16:31:10 -0800734 }
735 return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700736}
737
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800738// Opens a socket and returns its file descriptor.
739static int open_socket(const char* service);
740
Nandana Duttd2f5f082019-01-18 17:13:52 +0000741Dumpstate::ConsentCallback::ConsentCallback() : result_(UNAVAILABLE), start_time_(Nanotime()) {
742}
743
744android::binder::Status Dumpstate::ConsentCallback::onReportApproved() {
745 std::lock_guard<std::mutex> lock(lock_);
746 result_ = APPROVED;
747 MYLOGD("User approved consent to share bugreport\n");
Paul Chang0d2aad72020-02-13 20:04:03 +0800748
749 // Maybe copy screenshot so calling app can display the screenshot to the user as soon as
750 // consent is granted.
751 if (ds.options_->is_screenshot_copied) {
752 return android::binder::Status::ok();
753 }
754
755 if (!ds.options_->do_screenshot || ds.options_->screenshot_fd.get() == -1 ||
756 !ds.do_early_screenshot_) {
757 return android::binder::Status::ok();
758 }
759
760 bool copy_succeeded = android::os::CopyFileToFd(ds.screenshot_path_,
761 ds.options_->screenshot_fd.get());
762 ds.options_->is_screenshot_copied = copy_succeeded;
763 if (copy_succeeded) {
764 android::os::UnlinkAndLogOnError(ds.screenshot_path_);
765 }
Nandana Duttd2f5f082019-01-18 17:13:52 +0000766 return android::binder::Status::ok();
767}
768
769android::binder::Status Dumpstate::ConsentCallback::onReportDenied() {
770 std::lock_guard<std::mutex> lock(lock_);
771 result_ = DENIED;
772 MYLOGW("User denied consent to share bugreport\n");
773 return android::binder::Status::ok();
774}
775
776UserConsentResult Dumpstate::ConsentCallback::getResult() {
777 std::lock_guard<std::mutex> lock(lock_);
778 return result_;
779}
780
781uint64_t Dumpstate::ConsentCallback::getElapsedTimeMs() const {
Hunter Knepshieldf0a39052020-01-03 14:53:04 -0800782 return (Nanotime() - start_time_) / NANOS_PER_MILLI;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000783}
784
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700785void Dumpstate::PrintHeader() const {
Mårten Kongstad60195a72022-09-20 14:14:20 +0200786 std::string build, fingerprint, radio, bootloader, network, sdkversion;
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700787 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700788
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700789 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
790 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700791 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
792 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
793 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
Mårten Kongstad60195a72022-09-20 14:14:20 +0200794 sdkversion = android::base::GetProperty("ro.build.version.sdk", "(unknown)");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700795 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
Colin Crossf45fa6b2012-03-26 12:38:26 -0700796
Felipe Lemed8b94e52016-12-08 10:21:44 -0800797 printf("========================================================\n");
798 printf("== dumpstate: %s\n", date);
799 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700800
Felipe Lemed8b94e52016-12-08 10:21:44 -0800801 printf("\n");
802 printf("Build: %s\n", build.c_str());
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700803 // NOTE: fingerprint entry format is important for other tools.
Felipe Lemed8b94e52016-12-08 10:21:44 -0800804 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
805 printf("Bootloader: %s\n", bootloader.c_str());
806 printf("Radio: %s\n", radio.c_str());
807 printf("Network: %s\n", network.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100808 int64_t module_metadata_version = android::os::GetModuleMetadataVersion();
809 if (module_metadata_version != 0) {
810 printf("Module Metadata version: %" PRId64 "\n", module_metadata_version);
811 }
Mårten Kongstad60195a72022-09-20 14:14:20 +0200812 printf("Android SDK version: %s\n", sdkversion.c_str());
813 printf("SDK extensions: ");
814 RunCommandToFd(STDOUT_FILENO, "", {SDK_EXT_INFO, "--header"},
815 CommandOptions::WithTimeout(1).Always().DropRoot().Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700816
Felipe Lemed8b94e52016-12-08 10:21:44 -0800817 printf("Kernel: ");
Felipe Lemef0292972016-11-22 13:57:05 -0800818 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
Felipe Lemed8b94e52016-12-08 10:21:44 -0800819 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
Devin Moore09fde8d2023-03-21 16:28:22 +0000820 printf("Bootconfig: ");
821 DumpFileToFd(STDOUT_FILENO, "", "/proc/bootconfig");
Felipe Leme7709f8a2017-12-05 09:30:09 -0800822 printf("Uptime: ");
823 RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"},
824 CommandOptions::WithTimeout(1).Always().Build());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800825 printf("Bugreport format version: %s\n", version_.c_str());
Kevin Jeonfa64e642023-07-27 11:36:41 -0400826 printf(
827 "Dumpstate info: id=%d pid=%d dry_run=%d parallel_run=%d strict_run=%d args=%s "
828 "bugreport_mode=%s\n",
829 id_, pid_, PropertiesHelper::IsDryRun(), PropertiesHelper::IsParallelRun(),
830 PropertiesHelper::IsStrictRun(), options_->args.c_str(),
831 options_->bugreport_mode_string.c_str());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800832 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800833}
834
Felipe Leme24b66ee2016-06-16 10:55:26 -0700835// List of file extensions that can cause a zip file attachment to be rejected by some email
836// service providers.
837static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
838 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
839 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
840 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
841};
842
Vishnu Naire97d6122018-01-18 13:58:56 -0800843status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd,
844 std::chrono::milliseconds timeout = 0ms) {
Felipe Leme24b66ee2016-06-16 10:55:26 -0700845 std::string valid_name = entry_name;
846
847 // Rename extension if necessary.
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -0700848 size_t idx = entry_name.rfind('.');
Felipe Leme24b66ee2016-06-16 10:55:26 -0700849 if (idx != std::string::npos) {
850 std::string extension = entry_name.substr(idx);
851 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
852 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
853 valid_name = entry_name + ".renamed";
854 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
855 }
856 }
857
Felipe Leme6fe9db62016-02-12 09:04:16 -0800858 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
859 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Kevin Jeon9bbe0ac2022-05-05 22:05:43 +0000860 size_t flags = ZipWriter::kCompress | ZipWriter::kDefaultCompression;
861 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), flags,
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700862 get_mtime(fd, ds.now_));
Felipe Leme1d486fe2016-10-14 18:06:47 -0700863 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700864 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700865 ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800866 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800867 }
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000868 bool finished_entry = false;
869 auto finish_entry = [this, &finished_entry] {
870 if (!finished_entry) {
871 // This should only be called when we're going to return an earlier error,
872 // which would've been logged. This may imply the file is already corrupt
873 // and any further logging from FinishEntry is more likely to mislead than
874 // not.
875 this->zip_writer_->FinishEntry();
876 }
877 };
878 auto scope_guard = android::base::make_scope_guard(finish_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -0800879 auto start = std::chrono::steady_clock::now();
880 auto end = start + timeout;
881 struct pollfd pfd = {fd, POLLIN};
Felipe Lemee82a27d2016-01-05 13:35:44 -0800882
Felipe Leme770410d2016-01-26 17:07:14 -0800883 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800884 while (1) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800885 if (timeout.count() > 0) {
886 // lambda to recalculate the timeout.
887 auto time_left_ms = [end]() {
888 auto now = std::chrono::steady_clock::now();
889 auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
890 return std::max(diff.count(), 0LL);
891 };
892
893 int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
894 if (rc < 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000895 MYLOGE("Error in poll while adding from fd to zip entry %s:%s\n",
896 entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800897 return -errno;
898 } else if (rc == 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000899 MYLOGE("Timed out adding from fd to zip entry %s:%s Timeout:%lldms\n",
Vishnu Naire97d6122018-01-18 13:58:56 -0800900 entry_name.c_str(), strerror(errno), timeout.count());
901 return TIMED_OUT;
902 }
903 }
904
Zach Riggle22200402016-08-18 01:01:24 -0400905 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800906 if (bytes_read == 0) {
907 break;
908 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800909 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800910 return -errno;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800911 }
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700912 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800913 if (err) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700914 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800915 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800916 }
917 }
918
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700919 err = zip_writer_->FinishEntry();
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000920 finished_entry = true;
Felipe Leme1d486fe2016-10-14 18:06:47 -0700921 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700922 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800923 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800924 }
925
Vishnu Naire97d6122018-01-18 13:58:56 -0800926 return OK;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800927}
928
Felipe Leme1d486fe2016-10-14 18:06:47 -0700929bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
930 android::base::unique_fd fd(
931 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700932 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800933 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800934 return false;
935 }
936
Vishnu Naire97d6122018-01-18 13:58:56 -0800937 return (AddZipEntryFromFd(entry_name, fd.get()) == OK);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800938}
939
940/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700941static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800942 return (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) == OK) ? 0 : 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800943}
944
Felipe Leme1d486fe2016-10-14 18:06:47 -0700945void Dumpstate::AddDir(const std::string& dir, bool recursive) {
Felipe Leme678727a2016-09-21 17:22:11 -0700946 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
Felipe Leme46b85da2016-11-21 17:40:45 -0800947 DurationReporter duration_reporter(dir, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700948 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800949}
950
Felipe Leme1d486fe2016-10-14 18:06:47 -0700951bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800952 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Kevin Jeon9bbe0ac2022-05-05 22:05:43 +0000953 size_t flags = ZipWriter::kCompress | ZipWriter::kDefaultCompression;
954 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), flags, ds.now_);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700955 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700956 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700957 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800958 return false;
959 }
960
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700961 err = zip_writer_->WriteBytes(content.c_str(), content.length());
Felipe Leme1d486fe2016-10-14 18:06:47 -0700962 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700963 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700964 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800965 return false;
966 }
967
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700968 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700969 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700970 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800971 return false;
972 }
973
974 return true;
975}
976
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800977static void DoKmsg() {
978 struct stat st;
979 if (!stat(PSTORE_LAST_KMSG, &st)) {
980 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
981 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
982 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
983 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
984 } else {
985 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
986 DumpFile("LAST KMSG", "/proc/last_kmsg");
987 }
988}
989
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800990static void DoKernelLogcat() {
Yao Chenbe3bbc12018-01-17 16:31:10 -0800991 unsigned long timeout_ms = logcat_timeout({"kernel"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800992 RunCommand(
993 "KERNEL LOG",
994 {"logcat", "-b", "kernel", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
995 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
996}
997
Nandana Duttdb379fa2019-10-09 16:54:41 +0100998static void DoSystemLogcat(time_t since) {
999 char since_str[80];
1000 strftime(since_str, sizeof(since_str), "%Y-%m-%d %H:%M:%S.000", localtime(&since));
1001
1002 unsigned long timeout_ms = logcat_timeout({"main", "system", "crash"});
1003 RunCommand("SYSTEM LOG",
1004 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v", "-T",
1005 since_str},
1006 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1007}
1008
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001009static void DoRadioLogcat() {
1010 unsigned long timeout_ms = logcat_timeout({"radio"});
1011 RunCommand(
1012 "RADIO LOG",
1013 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1014 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
1015}
1016
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001017static void DoLogcat() {
Vishnu Nair6921f802017-11-22 09:17:23 -08001018 unsigned long timeout_ms;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001019 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
1020 // calculate timeout
Yao Chenbe3bbc12018-01-17 16:31:10 -08001021 timeout_ms = logcat_timeout({"main", "system", "crash"});
Tony Makae737652017-03-30 17:47:09 +01001022 RunCommand("SYSTEM LOG",
Vishnu Nair6921f802017-11-22 09:17:23 -08001023 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1024 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -08001025 timeout_ms = logcat_timeout({"events"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001026 RunCommand(
1027 "EVENT LOG",
1028 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001029 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Yao Chenbe3bbc12018-01-17 16:31:10 -08001030 timeout_ms = logcat_timeout({"stats"});
1031 RunCommand(
1032 "STATS LOG",
1033 {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001034 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001035 DoRadioLogcat();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001036
1037 RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
1038
1039 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001040 RunCommand("LAST LOGCAT", {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable",
1041 "-v", "uid", "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001042}
1043
Mike Ma5c267872019-08-21 11:31:34 -07001044static void DumpIncidentReport() {
Mike Ma5c267872019-08-21 11:31:34 -07001045 const std::string path = ds.bugreport_internal_dir_ + "/tmp_incident_report";
1046 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1047 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1048 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1049 if (fd < 0) {
1050 MYLOGE("Could not open %s to dump incident report.\n", path.c_str());
1051 return;
1052 }
Kevin Jeonfa64e642023-07-27 11:36:41 -04001053 RunCommandToFd(fd, "", {"incident", "-u"},
1054 CommandOptions::WithTimeout(PropertiesHelper::IsStrictRun() ? 20 : 120).Build());
Mike Ma5c267872019-08-21 11:31:34 -07001055 bool empty = 0 == lseek(fd, 0, SEEK_END);
1056 if (!empty) {
1057 // Use a different name from "incident.proto"
1058 // /proto/incident.proto is reserved for incident service dump
1059 // i.e. metadata for debugging.
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001060 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "incident_report" + kProtoExt,
1061 path);
1062 } else {
1063 unlink(path.c_str());
Mike Ma5c267872019-08-21 11:31:34 -07001064 }
Mike Ma5c267872019-08-21 11:31:34 -07001065}
1066
Aaron Huang24d215d2022-04-27 18:51:16 +08001067static void DumpNetstatsProto() {
1068 const std::string path = ds.bugreport_internal_dir_ + "/tmp_netstats_proto";
1069 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1070 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1071 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1072 if (fd < 0) {
1073 MYLOGE("Could not open %s to dump netstats proto.\n", path.c_str());
1074 return;
1075 }
1076 RunCommandToFd(fd, "", {"dumpsys", "netstats", "--proto"},
Kevin Jeon2fb3dd62022-09-28 18:48:55 +00001077 CommandOptions::WithTimeout(5).Build());
Aaron Huang24d215d2022-04-27 18:51:16 +08001078 bool empty = 0 == lseek(fd, 0, SEEK_END);
1079 if (!empty) {
1080 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "netstats" + kProtoExt,
1081 path);
1082 } else {
1083 unlink(path.c_str());
1084 }
1085}
1086
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001087static void MaybeAddSystemTraceToZip() {
1088 // This function copies into the .zip the system trace that was snapshotted
1089 // by the early call to MaybeSnapshotSystemTrace(), if any background
1090 // tracing was happening.
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001091 if (!ds.has_system_trace_) {
1092 // No background trace was happening at the time dumpstate was invoked.
1093 return;
1094 }
1095 ds.AddZipEntry(
1096 ZIP_ROOT_DIR + SYSTEM_TRACE_SNAPSHOT,
1097 SYSTEM_TRACE_SNAPSHOT);
1098 android::os::UnlinkAndLogOnError(SYSTEM_TRACE_SNAPSHOT);
1099}
1100
Sunny Goyal35949782019-11-19 15:54:36 -08001101static void DumpVisibleWindowViews() {
Sunny Goyal35949782019-11-19 15:54:36 -08001102 DurationReporter duration_reporter("VISIBLE WINDOW VIEWS");
1103 const std::string path = ds.bugreport_internal_dir_ + "/tmp_visible_window_views";
1104 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1105 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1106 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1107 if (fd < 0) {
1108 MYLOGE("Could not open %s to dump visible views.\n", path.c_str());
1109 return;
1110 }
1111 RunCommandToFd(fd, "", {"cmd", "window", "dump-visible-window-views"},
Kevin Jeon774abde2022-09-28 18:20:43 +00001112 CommandOptions::WithTimeout(10).Build());
Sunny Goyal35949782019-11-19 15:54:36 -08001113 bool empty = 0 == lseek(fd, 0, SEEK_END);
1114 if (!empty) {
1115 ds.AddZipEntry("visible_windows.zip", path);
1116 } else {
1117 MYLOGW("Failed to dump visible windows\n");
1118 }
1119 unlink(path.c_str());
1120}
1121
Jayachandran Ca94c7172017-06-10 15:08:12 -07001122static void DumpIpTablesAsRoot() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001123 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
1124 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +09001125 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001126 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +09001127 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
1128 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
1129 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
1130 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001131}
1132
Woody Lin20767a92022-11-29 15:50:24 +08001133static void DumpShutdownCheckpoints() {
1134 const bool shutdown_checkpoints_dumped = AddDumps(
1135 ds.shutdown_checkpoints_.begin(), ds.shutdown_checkpoints_.end(),
1136 "SHUTDOWN CHECKPOINTS", false /* add_to_zip */);
1137 if (!shutdown_checkpoints_dumped) {
1138 printf("*** NO SHUTDOWN CHECKPOINTS to dump in %s\n\n",
1139 SHUTDOWN_CHECKPOINTS_DIR.c_str());
1140 }
1141}
1142
David Andersond9ba4752018-12-11 18:26:59 -08001143static void DumpDynamicPartitionInfo() {
1144 if (!::android::base::GetBoolProperty("ro.boot.dynamic_partitions", false)) {
1145 return;
1146 }
1147
1148 RunCommand("LPDUMP", {"lpdump", "--all"});
David Anderson6650ade2019-10-02 15:18:59 -07001149 RunCommand("DEVICE-MAPPER", {"gsid", "dump-device-mapper"});
David Andersond9ba4752018-12-11 18:26:59 -08001150}
1151
Chris Morin5a50d482022-02-01 17:41:18 -08001152static void AddAnrTraceDir(const std::string& anr_traces_dir) {
Narayan Kamath8f788292017-05-25 13:20:39 +01001153 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
1154 anr_traces_dir.c_str());
1155
1156 // If we're here, dump_traces_path will always be a temporary file
1157 // (created with mkostemp or similar) that contains dumps taken earlier
1158 // on in the process.
1159 if (dump_traces_path != nullptr) {
Chris Morin5a50d482022-02-01 17:41:18 -08001160 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
1161 dump_traces_path);
1162 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
Narayan Kamath8f788292017-05-25 13:20:39 +01001163
1164 const int ret = unlink(dump_traces_path);
1165 if (ret == -1) {
1166 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
1167 strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -07001168 }
1169 }
1170
Narayan Kamathbd863722017-06-01 18:50:12 +01001171 // Add a specific message for the first ANR Dump.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001172 if (ds.anr_data_.size() > 0) {
Chris Morin5a50d482022-02-01 17:41:18 -08001173 // The "last" ANR will always be present in the body of the main entry.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001174 AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1,
Chris Morin5a50d482022-02-01 17:41:18 -08001175 "VM TRACES AT LAST ANR", false /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001176
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001177 // Historical ANRs are always included as separate entries in the bugreport zip file.
Chris Morin5a50d482022-02-01 17:41:18 -08001178 AddDumps(ds.anr_data_.begin(), ds.anr_data_.end(),
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001179 "HISTORICAL ANR", true /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001180 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +01001181 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
1182 }
1183}
1184
1185static void AddAnrTraceFiles() {
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001186 std::string anr_traces_dir = "/data/anr";
Narayan Kamath8f788292017-05-25 13:20:39 +01001187
Chris Morin5a50d482022-02-01 17:41:18 -08001188 AddAnrTraceDir(anr_traces_dir);
Narayan Kamath8f788292017-05-25 13:20:39 +01001189
Makoto Onuki83ec63f2019-01-31 17:08:59 -08001190 RunCommand("ANR FILES", {"ls", "-lt", ANR_DIR});
1191
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001192 // Slow traces for slow operations.
Felipe Lemee184f662016-10-27 10:04:47 -07001193 struct stat st;
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001194 int i = 0;
1195 while (true) {
1196 const std::string slow_trace_path =
1197 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
1198 if (stat(slow_trace_path.c_str(), &st)) {
1199 // No traces file at this index, done with the files.
1200 break;
Felipe Lemee184f662016-10-27 10:04:47 -07001201 }
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001202 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
1203 i++;
Felipe Lemee184f662016-10-27 10:04:47 -07001204 }
1205}
1206
Wei Wang509bb5d2017-06-09 14:42:12 -07001207static void DumpBlockStatFiles() {
1208 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -07001209
Wei Wang1dc1ef52017-06-12 11:28:37 -07001210 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
1211
1212 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001213 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1214 return;
1215 }
1216
1217 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -07001218 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001219 if ((d->d_name[0] == '.')
1220 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1221 || (d->d_name[1] == '\0'))) {
1222 continue;
1223 }
1224 const std::string new_path =
1225 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1226 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1227 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1228 printf("\n");
1229 }
Wei Wang1dc1ef52017-06-12 11:28:37 -07001230 return;
Wei Wang509bb5d2017-06-09 14:42:12 -07001231}
Jayachandran Ca94c7172017-06-10 15:08:12 -07001232
1233static void DumpPacketStats() {
1234 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
Jayachandran Ca94c7172017-06-10 15:08:12 -07001235}
1236
1237static void DumpIpAddrAndRules() {
1238 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
1239 RunCommand("NETWORK INTERFACES", {"ip", "link"});
1240 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1241 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1242 RunCommand("IP RULES", {"ip", "rule", "show"});
1243 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1244}
1245
Nandana Dutt5c390032019-03-12 10:52:56 +00001246static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, int priority,
1247 std::chrono::milliseconds timeout,
1248 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001249 auto start = std::chrono::steady_clock::now();
Vishnu Naire97d6122018-01-18 13:58:56 -08001250 sp<android::IServiceManager> sm = defaultServiceManager();
1251 Dumpsys dumpsys(sm.get());
Vishnu Naire97d6122018-01-18 13:58:56 -08001252 Vector<String16> args;
1253 Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
Vishnu Naire97d6122018-01-18 13:58:56 -08001254 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1255 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001256 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001257 std::string path(title);
1258 path.append(" - ").append(String8(service).c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -08001259 size_t bytes_written = 0;
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001260 if (PropertiesHelper::IsDryRun()) {
1261 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1262 dumpsys.writeDumpFooter(STDOUT_FILENO, service, std::chrono::milliseconds(1));
1263 } else {
Devin Mooref492c1a2023-03-15 19:19:03 +00001264 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP | Dumpsys::TYPE_PID |
1265 Dumpsys::TYPE_CLIENTS | Dumpsys::TYPE_THREAD,
Devin Mooreae68df22023-02-24 20:59:51 +00001266 service, args);
1267 if (status == OK) {
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001268 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1269 std::chrono::duration<double> elapsed_seconds;
1270 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH &&
1271 service == String16("meminfo")) {
1272 // Use a longer timeout for meminfo, since 30s is not always enough.
1273 status = dumpsys.writeDump(STDOUT_FILENO, service, 60s,
1274 /* as_proto = */ false, elapsed_seconds,
1275 bytes_written);
1276 } else {
1277 status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
1278 /* as_proto = */ false, elapsed_seconds,
1279 bytes_written);
1280 }
1281 dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
1282 bool dump_complete = (status == OK);
1283 dumpsys.stopDumpThread(dump_complete);
Devin Moorecdfa4602023-03-16 20:49:39 +00001284 } else {
1285 MYLOGE("Failed to start dump thread for service: %s, status: %d",
1286 String8(service).c_str(), status);
Gavin Corkeryfac7e2b2021-07-08 22:39:02 +01001287 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001288 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001289
1290 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1291 std::chrono::steady_clock::now() - start);
1292 if (elapsed_duration > timeout) {
1293 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1294 elapsed_duration.count());
1295 break;
1296 }
1297 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001298 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001299}
1300
Vishnu Nair64afc022018-02-01 15:29:34 -08001301static void RunDumpsysText(const std::string& title, int priority,
1302 std::chrono::milliseconds timeout,
1303 std::chrono::milliseconds service_timeout) {
1304 DurationReporter duration_reporter(title);
1305 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1306 fsync(STDOUT_FILENO);
1307 RunDumpsysTextByPriority(title, priority, timeout, service_timeout);
1308}
1309
1310/* Dump all services registered with Normal or Default priority. */
Nandana Dutt5c390032019-03-12 10:52:56 +00001311static Dumpstate::RunStatus RunDumpsysTextNormalPriority(const std::string& title,
1312 std::chrono::milliseconds timeout,
1313 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001314 DurationReporter duration_reporter(title);
1315 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1316 fsync(STDOUT_FILENO);
1317 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout,
1318 service_timeout);
Nandana Dutt5c390032019-03-12 10:52:56 +00001319
1320 RETURN_IF_USER_DENIED_CONSENT();
1321
1322 return RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1323 service_timeout);
Vishnu Nair64afc022018-02-01 15:29:34 -08001324}
1325
Nandana Dutt5c390032019-03-12 10:52:56 +00001326static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priority,
1327 std::chrono::milliseconds timeout,
1328 std::chrono::milliseconds service_timeout) {
Vishnu Naire97d6122018-01-18 13:58:56 -08001329 sp<android::IServiceManager> sm = defaultServiceManager();
1330 Dumpsys dumpsys(sm.get());
1331 Vector<String16> args;
1332 Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
1333 DurationReporter duration_reporter(title);
1334
1335 auto start = std::chrono::steady_clock::now();
1336 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
1337 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001338 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001339 std::string path(kProtoPath);
1340 path.append(String8(service).c_str());
1341 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
1342 path.append("_CRITICAL");
1343 } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
1344 path.append("_HIGH");
1345 }
1346 path.append(kProtoExt);
Steven Morelandcbd69fc2021-07-20 20:45:43 +00001347 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP, service, args);
Vishnu Naire97d6122018-01-18 13:58:56 -08001348 if (status == OK) {
1349 status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
1350 bool dumpTerminated = (status == OK);
1351 dumpsys.stopDumpThread(dumpTerminated);
1352 }
1353 ZipWriter::FileEntry file_entry;
1354 ds.zip_writer_->GetLastEntry(&file_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -08001355
1356 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1357 std::chrono::steady_clock::now() - start);
1358 if (elapsed_duration > timeout) {
1359 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1360 elapsed_duration.count());
1361 break;
1362 }
1363 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001364 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001365}
1366
Nandana Dutta7db6342018-11-21 14:53:34 +00001367// Runs dumpsys on services that must dump first and will take less than 100ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001368static Dumpstate::RunStatus RunDumpsysCritical() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001369 RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1370 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Nandana Dutt5c390032019-03-12 10:52:56 +00001371
1372 RETURN_IF_USER_DENIED_CONSENT();
1373
1374 return RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1375 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Vishnu Nair780b1282017-10-10 13:57:24 -07001376}
1377
1378// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001379static Dumpstate::RunStatus RunDumpsysHigh() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001380 // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
1381 // high priority. Reduce timeout once they are able to dump in a shorter time or
1382 // moved to a parallel task.
1383 RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1384 /* timeout= */ 90s, /* service_timeout= */ 30s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001385
1386 RETURN_IF_USER_DENIED_CONSENT();
1387
1388 return RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1389 /* timeout= */ 5s, /* service_timeout= */ 1s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001390}
1391
1392// Runs dumpsys on services that must dump but can take up to 10s to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001393static Dumpstate::RunStatus RunDumpsysNormal() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001394 RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001395
1396 RETURN_IF_USER_DENIED_CONSENT();
1397
1398 return RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1399 /* timeout= */ 90s, /* service_timeout= */ 10s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001400}
1401
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001402/*
1403 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1404 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1405 * if it's not running in the parallel task.
1406 */
1407static void DumpHals(int out_fd = STDOUT_FILENO) {
Yifan Hong30528a22020-08-07 18:24:06 -07001408 RunCommand("HARDWARE HALS", {"lshal", "--all", "--types=all"},
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001409 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build(),
1410 false, out_fd);
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001411
Steven Moreland44cd9482018-01-04 16:24:13 -08001412 using android::hidl::manager::V1_0::IServiceManager;
1413 using android::hardware::defaultServiceManager;
1414
1415 sp<IServiceManager> sm = defaultServiceManager();
1416 if (sm == nullptr) {
1417 MYLOGE("Could not retrieve hwservicemanager to dump hals.\n");
1418 return;
1419 }
1420
1421 auto ret = sm->list([&](const auto& interfaces) {
1422 for (const std::string& interface : interfaces) {
1423 std::string cleanName = interface;
Steven Morelandc6b1fc22023-07-26 23:53:58 +00001424 std::replace_if(
1425 cleanName.begin(), cleanName.end(),
1426 [](char c) {
1427 return !isalnum(c) && std::string("@-_.").find(c) == std::string::npos;
1428 },
1429 '_');
Nandana Dutt979388e2018-11-30 16:48:55 +00001430 const std::string path = ds.bugreport_internal_dir_ + "/lshal_debug_" + cleanName;
Steven Moreland44cd9482018-01-04 16:24:13 -08001431
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001432 bool empty = false;
Steven Moreland44cd9482018-01-04 16:24:13 -08001433 {
1434 auto fd = android::base::unique_fd(
1435 TEMP_FAILURE_RETRY(open(path.c_str(),
1436 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1437 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1438 if (fd < 0) {
1439 MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str());
1440 continue;
1441 }
1442 RunCommandToFd(fd,
1443 "",
Steven Morelandc81cd3c2018-01-18 14:36:26 -08001444 {"lshal", "debug", "-E", interface},
Steven Moreland44cd9482018-01-04 16:24:13 -08001445 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1446
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001447 empty = 0 == lseek(fd, 0, SEEK_END);
Steven Moreland44cd9482018-01-04 16:24:13 -08001448 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001449 if (!empty) {
1450 ds.EnqueueAddZipEntryAndCleanupIfNeeded("lshal-debug/" + cleanName + ".txt",
1451 path);
1452 } else {
1453 unlink(path.c_str());
1454 }
Steven Moreland44cd9482018-01-04 16:24:13 -08001455 }
1456 });
1457
1458 if (!ret.isOk()) {
1459 MYLOGE("Could not list hals from hwservicemanager.\n");
1460 }
1461}
1462
Devin Moore8df81bb2022-06-08 22:47:02 +00001463// Dump all of the files that make up the vendor interface.
1464// See the files listed in dumpFileList() for the latest list of files.
1465static void DumpVintf() {
Devin Moore16271d92022-09-22 18:28:48 +00001466
1467 const std::string sku = android::base::GetProperty("ro.boot.product.hardware.sku", "");
1468 const auto vintfFiles = android::vintf::details::dumpFileList(sku);
Devin Moore8df81bb2022-06-08 22:47:02 +00001469 for (const auto vintfFile : vintfFiles) {
1470 struct stat st;
1471 if (stat(vintfFile.c_str(), &st) == 0) {
1472 if (S_ISDIR(st.st_mode)) {
1473 ds.AddDir(vintfFile, true /* recursive */);
1474 } else {
1475 ds.EnqueueAddZipEntryAndCleanupIfNeeded(ZIP_ROOT_DIR + vintfFile,
1476 vintfFile);
1477 }
1478 }
1479 }
1480}
1481
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001482static void DumpExternalFragmentationInfo() {
1483 struct stat st;
1484 if (stat("/proc/buddyinfo", &st) != 0) {
1485 MYLOGE("Unable to dump external fragmentation info\n");
1486 return;
1487 }
1488
1489 printf("------ EXTERNAL FRAGMENTATION INFO ------\n");
1490 std::ifstream ifs("/proc/buddyinfo");
1491 auto unusable_index_regex = std::regex{"Node\\s+([0-9]+),\\s+zone\\s+(\\S+)\\s+(.*)"};
1492 for (std::string line; std::getline(ifs, line);) {
1493 std::smatch match_results;
1494 if (std::regex_match(line, match_results, unusable_index_regex)) {
1495 std::stringstream free_pages(std::string{match_results[3]});
1496 std::vector<int> free_pages_per_order(std::istream_iterator<int>{free_pages},
1497 std::istream_iterator<int>());
1498
1499 int total_free_pages = 0;
1500 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1501 total_free_pages += (free_pages_per_order[i] * std::pow(2, i));
1502 }
1503
1504 printf("Node %s, zone %8s", match_results[1].str().c_str(),
1505 match_results[2].str().c_str());
1506
1507 int usable_free_pages = total_free_pages;
1508 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1509 auto unusable_index = (total_free_pages - usable_free_pages) /
1510 static_cast<double>(total_free_pages);
1511 printf(" %5.3f", unusable_index);
1512 usable_free_pages -= (free_pages_per_order[i] * std::pow(2, i));
1513 }
1514
1515 printf("\n");
1516 }
1517 }
1518 printf("\n");
1519}
1520
mhasankd451a472020-05-26 18:02:39 -07001521static void DumpstateLimitedOnly() {
1522 // Trimmed-down version of dumpstate to only include a whitelisted
1523 // set of logs (system log, event log, and system server / system app
1524 // crashes, and networking logs). See b/136273873 and b/138459828
1525 // for context.
1526 DurationReporter duration_reporter("DUMPSTATE");
1527 unsigned long timeout_ms;
1528 // calculate timeout
1529 timeout_ms = logcat_timeout({"main", "system", "crash"});
1530 RunCommand("SYSTEM LOG",
1531 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1532 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1533 timeout_ms = logcat_timeout({"events"});
1534 RunCommand(
1535 "EVENT LOG",
1536 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1537 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1538
1539 printf("========================================================\n");
1540 printf("== Networking Service\n");
1541 printf("========================================================\n");
1542
1543 RunDumpsys("DUMPSYS NETWORK_SERVICE_LIMITED", {"wifi", "-a"},
1544 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hugo Benichiaa162682020-10-30 23:28:56 +09001545 RunDumpsys("DUMPSYS CONNECTIVITY REQUESTS", {"connectivity", "requests"},
1546 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
mhasankd451a472020-05-26 18:02:39 -07001547
1548 printf("========================================================\n");
1549 printf("== Dropbox crashes\n");
1550 printf("========================================================\n");
1551
1552 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1553 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1554
1555 printf("========================================================\n");
1556 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1557 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1558 printf("========================================================\n");
1559 printf("== dumpstate: done (id %d)\n", ds.id_);
1560 printf("========================================================\n");
1561}
1562
Rhed Jaoe017f982020-07-21 17:58:41 +08001563/*
1564 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1565 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1566 * if it's not running in the parallel task.
1567 */
1568static void DumpCheckins(int out_fd = STDOUT_FILENO) {
1569 dprintf(out_fd, "========================================================\n");
1570 dprintf(out_fd, "== Checkins\n");
1571 dprintf(out_fd, "========================================================\n");
1572
1573 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"}, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001574 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"}, out_fd);
1575 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"}, out_fd);
1576 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"}, out_fd);
1577 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"}, out_fd);
1578}
1579
1580/*
1581 * Runs dumpsys on activity service to dump all application activities, services
1582 * and providers in the device.
1583 *
1584 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1585 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1586 * if it's not running in the parallel task.
1587 */
1588static void DumpAppInfos(int out_fd = STDOUT_FILENO) {
1589 dprintf(out_fd, "========================================================\n");
1590 dprintf(out_fd, "== Running Application Activities\n");
1591 dprintf(out_fd, "========================================================\n");
1592
1593 // The following dumpsys internally collects output from running apps, so it can take a long
1594 // time. So let's extend the timeout.
1595
1596 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1597
1598 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1599
1600 dprintf(out_fd, "========================================================\n");
1601 dprintf(out_fd, "== Running Application Services (platform)\n");
1602 dprintf(out_fd, "========================================================\n");
1603
1604 RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
1605 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1606
1607 dprintf(out_fd, "========================================================\n");
1608 dprintf(out_fd, "== Running Application Services (non-platform)\n");
1609 dprintf(out_fd, "========================================================\n");
1610
1611 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1612 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1613
1614 dprintf(out_fd, "========================================================\n");
1615 dprintf(out_fd, "== Running Application Providers (platform)\n");
1616 dprintf(out_fd, "========================================================\n");
1617
1618 RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
Rhed Jaob049f182021-01-11 21:08:43 +08001619 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001620
1621 dprintf(out_fd, "========================================================\n");
1622 dprintf(out_fd, "== Running Application Providers (non-platform)\n");
1623 dprintf(out_fd, "========================================================\n");
1624
1625 RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1626 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1627}
1628
Nandana Dutt5c390032019-03-12 10:52:56 +00001629// Dumps various things. Returns early with status USER_CONSENT_DENIED if user denies consent
1630// via the consent they are shown. Ignores other errors that occur while running various
1631// commands. The consent checking is currently done around long running tasks, which happen to
1632// be distributed fairly evenly throughout the function.
Kean Mariotti306633e2022-09-05 16:30:47 +00001633Dumpstate::RunStatus Dumpstate::dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001634 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001635
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001636 // Enqueue slow functions into the thread pool, if the parallel run is enabled.
Aaron Huang24d215d2022-04-27 18:51:16 +08001637 std::future<std::string> dump_hals, dump_incident_report, dump_board, dump_checkins,
Kean Mariotti306633e2022-09-05 16:30:47 +00001638 dump_netstats_report, post_process_ui_traces;
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001639 if (ds.dump_pool_) {
1640 // Pool was shutdown in DumpstateDefaultAfterCritical method in order to
Kean Mariotti306633e2022-09-05 16:30:47 +00001641 // drop root user. Restarts it.
1642 ds.dump_pool_->start(/* thread_counts = */3);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001643
Chris Morinbc223142022-02-04 14:17:11 -08001644 dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
1645 dump_incident_report = ds.dump_pool_->enqueueTask(
1646 DUMP_INCIDENT_REPORT_TASK, &DumpIncidentReport);
Aaron Huang24d215d2022-04-27 18:51:16 +08001647 dump_netstats_report = ds.dump_pool_->enqueueTask(
1648 DUMP_NETSTATS_PROTO_TASK, &DumpNetstatsProto);
Chris Morinbc223142022-02-04 14:17:11 -08001649 dump_board = ds.dump_pool_->enqueueTaskWithFd(
1650 DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
1651 dump_checkins = ds.dump_pool_->enqueueTaskWithFd(DUMP_CHECKINS_TASK, &DumpCheckins, _1);
Kean Mariotti306633e2022-09-05 16:30:47 +00001652 post_process_ui_traces = ds.dump_pool_->enqueueTask(
1653 POST_PROCESS_UI_TRACES_TASK, &Dumpstate::MaybePostProcessUiTraces, &ds);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001654 }
1655
Nandana Dutt5c390032019-03-12 10:52:56 +00001656 // Dump various things. Note that anything that takes "long" (i.e. several seconds) should
1657 // check intermittently (if it's intrerruptable like a foreach on pids) and/or should be wrapped
1658 // in a consent check (via RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK).
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001659 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001660 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001661 DumpBlockStatFiles();
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001662 DumpFile("MEMORY INFO", "/proc/meminfo");
1663 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001664 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001665
Kevin Jeon947922b2022-09-21 00:29:18 +00001666 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "BUGREPORT_PROCDUMP", {"bugreport_procdump"},
1667 CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001668
Sunny Goyal35949782019-11-19 15:54:36 -08001669 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpVisibleWindowViews);
1670
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001671 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1672 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1673 DumpFile("SLAB INFO", "/proc/slabinfo");
1674 DumpFile("ZONEINFO", "/proc/zoneinfo");
1675 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1676 DumpFile("BUDDYINFO", "/proc/buddyinfo");
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001677 DumpExternalFragmentationInfo();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001678
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001679 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001680
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001681 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001682 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001683
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001684 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001685 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_hals));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001686 } else {
1687 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_HALS_TASK, DumpHals);
1688 }
Steven Moreland81b429e2017-01-31 19:50:46 -08001689
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001690 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001691 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001692 struct stat s;
1693 if (stat("/proc/modules", &s) != 0) {
1694 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1695 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001696 RunCommand("LSMOD", {"lsmod"});
Woody Linc198f252021-05-04 16:37:11 +08001697 RunCommand("MODULES INFO",
1698 {"sh", "-c", "cat /proc/modules | cut -d' ' -f1 | "
1699 " while read MOD ; do echo modinfo:$MOD ; modinfo $MOD ; "
1700 "done"}, CommandOptions::AS_ROOT);
Felipe Lemee4eca582016-06-10 17:48:08 -07001701 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001702
Tom Cherryb87dbfa2020-07-28 11:28:53 -07001703 if (android::base::GetBoolProperty("ro.logd.kernel", false)) {
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001704 DoKernelLogcat();
1705 } else {
1706 do_dmesg();
1707 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001708
Devin Moore8df81bb2022-06-08 22:47:02 +00001709 DumpVintf();
1710
Felipe Lemef0292972016-11-22 13:57:05 -08001711 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001712
Jeff Brown1dc94e32014-09-11 14:15:27 -07001713 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001714 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001715
Jack Yu5a6b2e22020-08-14 18:13:35 +08001716 /* Dump Nfc NCI logs */
1717 ds.AddDir("/data/misc/nfc/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001718
Paul Chang0d2aad72020-02-13 20:04:03 +08001719 if (ds.options_->do_screenshot && !ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001720 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001721 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001722 }
1723
Felipe Lemee184f662016-10-27 10:04:47 -07001724 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001725
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001726 MaybeAddSystemTraceToZip();
1727
Narayan Kamath8f788292017-05-25 13:20:39 +01001728 // NOTE: tombstones are always added as separate entries in the zip archive
1729 // and are not interspersed with the main report.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001730 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
Narayan Kamathbd863722017-06-01 18:50:12 +01001731 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001732 if (!tombstones_dumped) {
1733 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001734 }
1735
Jayachandran Ca94c7172017-06-10 15:08:12 -07001736 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001737
Lorenzo Colitti807f2dd2022-05-27 12:48:37 +09001738 RunDumpsys("EBPF MAP STATS", {"connectivity", "trafficcontroller"});
Chenbo Feng276a3b62018-08-07 11:44:49 -07001739
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001740 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001741
Woody Lin20767a92022-11-29 15:50:24 +08001742 DumpShutdownCheckpoints();
1743
Jayachandran Ca94c7172017-06-10 15:08:12 -07001744 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001745
1746 dump_route_tables();
1747
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001748 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1749 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1750 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001751
Nandana Dutt5c390032019-03-12 10:52:56 +00001752 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysHigh);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001753
Chiachang Wang668ede42021-05-17 17:14:20 +08001754 // The dump mechanism in connectivity is refactored due to modularization work. Connectivity can
1755 // only register with a default priority(NORMAL priority). Dumpstate has to call connectivity
1756 // dump with priority parameters to dump high priority information.
1757 RunDumpsys("SERVICE HIGH connectivity", {"connectivity", "--dump-priority", "HIGH"},
1758 CommandOptions::WithTimeout(10).Build());
1759
Elliott Hughes23ccc622017-02-28 10:14:22 -08001760 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001761
Joe Onoratod38bc3a2023-06-29 15:48:28 -07001762 DumpFile("SYSTEM BUILD-TIME RELEASE FLAGS", "/system/etc/build_flags.json");
1763 DumpFile("SYSTEM_EXT BUILD-TIME RELEASE FLAGS", "/system_ext/etc/build_flags.json");
1764 DumpFile("PRODUCT BUILD-TIME RELEASE FLAGS", "/product/etc/build_flags.json");
1765 DumpFile("VENDOR BUILD-TIME RELEASE FLAGS", "/vendor/etc/build_flags.json");
1766
Mårten Kongstad5ad813f2023-09-28 10:09:18 +02001767 RunCommand("ACONFIG FLAGS", {PRINT_FLAGS},
1768 CommandOptions::WithTimeout(10).Always().DropRoot().Build());
Joe Onoratod38bc3a2023-06-29 15:48:28 -07001769
Jin Qianf334d662017-10-10 14:41:37 -07001770 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001771
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001772 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001773
Colin Crossf45fa6b2012-03-26 12:38:26 -07001774 /* Binder state is expensive to look at as it uses a lot of memory. */
Hridya Valsaraju920ba712020-02-09 16:27:01 -08001775 std::string binder_logs_dir = access("/dev/binderfs/binder_logs", R_OK) ?
1776 "/sys/kernel/debug/binder" : "/dev/binderfs/binder_logs";
1777
1778 DumpFile("BINDER FAILED TRANSACTION LOG", binder_logs_dir + "/failed_transaction_log");
1779 DumpFile("BINDER TRANSACTION LOG", binder_logs_dir + "/transaction_log");
1780 DumpFile("BINDER TRANSACTIONS", binder_logs_dir + "/transactions");
1781 DumpFile("BINDER STATS", binder_logs_dir + "/stats");
1782 DumpFile("BINDER STATE", binder_logs_dir + "/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001783
Yifan Hongd90cc652020-02-08 16:52:02 -08001784 ds.AddDir(SNAPSHOTCTL_LOG_DIR, false);
1785
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001786 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001787 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_board));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001788 } else {
1789 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
1790 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001791
Steven Moreland7440ddb2016-12-15 16:13:39 -08001792 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001793 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1794 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001795 // su does not exist on user builds, so try running without it.
1796 // This way any implementations of vril-dump that do not require
1797 // root can run on user builds.
1798 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001799 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001800 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001801 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001802 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001803 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001804 }
1805
Felipe Lemed8b94e52016-12-08 10:21:44 -08001806 printf("========================================================\n");
1807 printf("== Android Framework Services\n");
1808 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001809
Nandana Dutt5c390032019-03-12 10:52:56 +00001810 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001811
Jack He91ff2fe2021-02-18 18:23:43 -08001812 /* Dump Bluetooth HCI logs after getting bluetooth_manager dumpsys */
1813 ds.AddDir("/data/misc/bluetooth/logs", true);
1814
Rhed Jaoe017f982020-07-21 17:58:41 +08001815 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001816 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_checkins));
Rhed Jaoe017f982020-07-21 17:58:41 +08001817 } else {
1818 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_CHECKINS_TASK, DumpCheckins);
1819 }
Dianne Hackborn02bea972013-06-26 18:59:09 -07001820
Rhed Jaoc5f7ec32020-12-22 22:11:08 +08001821 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpAppInfos);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001822
Adrian Roos8b397ab2017-04-04 16:35:44 -07001823 printf("========================================================\n");
1824 printf("== Dropbox crashes\n");
1825 printf("========================================================\n");
1826
1827 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1828 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1829
Felipe Lemed8b94e52016-12-08 10:21:44 -08001830 printf("========================================================\n");
1831 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1832 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1833 printf("========================================================\n");
1834 printf("== dumpstate: done (id %d)\n", ds.id_);
1835 printf("========================================================\n");
Bookatz38472142018-09-28 10:20:24 -07001836
1837 printf("========================================================\n");
1838 printf("== Obtaining statsd metadata\n");
1839 printf("========================================================\n");
1840 // This differs from the usual dumpsys stats, which is the stats report data.
1841 RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
Mike Ma5c267872019-08-21 11:31:34 -07001842
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +09001843 // Add linker configuration directory
1844 ds.AddDir(LINKERCONFIG_DIR, true);
1845
Li Li830179f2022-01-04 12:53:29 -08001846 /* Dump frozen cgroupfs */
1847 dump_frozen_cgroupfs();
Li Li2eedd412021-06-30 15:11:53 -07001848
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001849 if (ds.dump_pool_) {
Aaron Huang24d215d2022-04-27 18:51:16 +08001850 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_netstats_report));
1851 } else {
1852 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_NETSTATS_PROTO_TASK,
1853 DumpNetstatsProto);
1854 }
1855
1856 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001857 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_incident_report));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001858 } else {
1859 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_INCIDENT_REPORT_TASK,
1860 DumpIncidentReport);
1861 }
Mike Ma5c267872019-08-21 11:31:34 -07001862
Kean Mariotti306633e2022-09-05 16:30:47 +00001863 if (ds.dump_pool_) {
1864 WaitForTask(std::move(post_process_ui_traces));
1865 } else {
1866 RUN_SLOW_FUNCTION_AND_LOG(POST_PROCESS_UI_TRACES_TASK, MaybePostProcessUiTraces);
1867 }
1868
1869 MaybeAddUiTracesToZip();
1870
Nandana Dutt5c390032019-03-12 10:52:56 +00001871 return Dumpstate::RunStatus::OK;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001872}
1873
Nandana Dutt5c390032019-03-12 10:52:56 +00001874/*
1875 * Dumps state for the default case; drops root after it's no longer necessary.
1876 *
1877 * Returns RunStatus::OK if everything went fine.
1878 * Returns RunStatus::ERROR if there was an error.
1879 * Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport
1880 * with the caller.
1881 */
Jichao Lie89d9c12019-11-21 19:02:51 -08001882Dumpstate::RunStatus Dumpstate::DumpstateDefaultAfterCritical() {
Nandana Duttdb379fa2019-10-09 16:54:41 +01001883 // Capture first logcat early on; useful to take a snapshot before dumpstate logs take over the
1884 // buffer.
1885 DoLogcat();
1886 // Capture timestamp after first logcat to use in next logcat
1887 time_t logcat_ts = time(nullptr);
1888
Nandana Dutt4be45d12018-09-26 15:04:23 +01001889 /* collect stack traces from Dalvik and native processes (needs root) */
Chris Morinbc223142022-02-04 14:17:11 -08001890 std::future<std::string> dump_traces;
Rhed Jao5377d792020-07-16 17:37:39 +08001891 if (dump_pool_) {
1892 RETURN_IF_USER_DENIED_CONSENT();
1893 // One thread is enough since we only need to enqueue DumpTraces here.
1894 dump_pool_->start(/* thread_counts = */1);
1895
1896 // DumpTraces takes long time, post it to the another thread in the
1897 // pool, if pool is available
Chris Morinbc223142022-02-04 14:17:11 -08001898 dump_traces = dump_pool_->enqueueTask(
1899 DUMP_TRACES_TASK, &Dumpstate::DumpTraces, &ds, &dump_traces_path);
Rhed Jao5377d792020-07-16 17:37:39 +08001900 } else {
1901 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_TRACES_TASK, ds.DumpTraces,
1902 &dump_traces_path);
1903 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001904
1905 /* Run some operations that require root. */
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001906 if (!PropertiesHelper::IsDryRun()) {
Chris Morinc2cba7a2022-02-01 17:06:50 -08001907 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX);
1908 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX);
Woody Lin20767a92022-11-29 15:50:24 +08001909 ds.shutdown_checkpoints_ = GetDumpFds(
1910 SHUTDOWN_CHECKPOINTS_DIR, SHUTDOWN_CHECKPOINTS_FILE_PREFIX);
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001911 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001912
1913 ds.AddDir(RECOVERY_DIR, true);
1914 ds.AddDir(RECOVERY_DATA_DIR, true);
1915 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
Kelvin Zhang6eaa0f92022-09-12 09:29:19 -07001916 ds.AddDir(UPDATE_ENGINE_PREF_DIR, true);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001917 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1918 if (!PropertiesHelper::IsUserBuild()) {
1919 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1920 ds.AddDir(PROFILE_DATA_DIR_REF, true);
Calin Juravlef84d3692020-04-28 15:31:12 -07001921 ds.AddZipEntry(ZIP_ROOT_DIR + PACKAGE_DEX_USE_LIST, PACKAGE_DEX_USE_LIST);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001922 }
Jerry Changa1df8a92020-01-02 16:03:39 +08001923 ds.AddDir(PREREBOOT_DATA_DIR, false);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001924 add_mountinfo();
Peter Collingbourne78aa2942023-02-15 14:50:31 -08001925 for (const char* path : {"/proc/cpuinfo", "/proc/meminfo"}) {
1926 ds.AddZipEntry(ZIP_ROOT_DIR + path, path);
1927 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001928 DumpIpTablesAsRoot();
David Andersond9ba4752018-12-11 18:26:59 -08001929 DumpDynamicPartitionInfo();
Yifan Hong3945e1b2019-10-29 12:59:23 -07001930 ds.AddDir(OTA_METADATA_DIR, true);
Jeff Sharkey9df29d52023-02-06 14:26:30 -07001931 if (!PropertiesHelper::IsUserBuild()) {
1932 // Include dropbox entry files inside ZIP, but exclude
1933 // noisy WTF and StrictMode entries
1934 dump_files("", DROPBOX_DIR, skip_wtf_strictmode, _add_file_from_fd);
1935 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001936
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001937 // Capture any IPSec policies in play. No keys are exposed here.
Nandana Dutt4be45d12018-09-26 15:04:23 +01001938 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1939
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001940 // Dump IPsec stats. No keys are exposed here.
1941 DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
1942
Nandana Dutt4be45d12018-09-26 15:04:23 +01001943 // Run ss as root so we can see socket marks.
1944 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1945
1946 // Run iotop as root to show top 100 IO threads
1947 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1948
Erick Reyese68df822019-02-11 14:46:36 -08001949 // Gather shared memory buffer info if the product implements it
Hridya Valsaraju1da80c52021-01-09 22:10:11 -08001950 RunCommand("Dmabuf dump", {"dmabuf_dump"});
1951 RunCommand("Dmabuf per-buffer/per-exporter/per-device stats", {"dmabuf_dump", "-b"});
Erick Reyese68df822019-02-11 14:46:36 -08001952
Minchan Kim22c6a1e2019-09-30 15:58:10 -07001953 DumpFile("PSI cpu", "/proc/pressure/cpu");
1954 DumpFile("PSI memory", "/proc/pressure/memory");
1955 DumpFile("PSI io", "/proc/pressure/io");
1956
Mårten Kongstad60195a72022-09-20 14:14:20 +02001957 RunCommand("SDK EXTENSIONS", {SDK_EXT_INFO, "--dump"},
1958 CommandOptions::WithTimeout(10).Always().DropRoot().Build());
1959
Rhed Jao5377d792020-07-16 17:37:39 +08001960 if (dump_pool_) {
1961 RETURN_IF_USER_DENIED_CONSENT();
Chris Morinbc223142022-02-04 14:17:11 -08001962 WaitForTask(std::move(dump_traces));
Rhed Jao5377d792020-07-16 17:37:39 +08001963
Chris Morinbc223142022-02-04 14:17:11 -08001964 // Current running thread in the pool is the root user also. Delete
1965 // the pool and make a new one later to ensure none of threads in the pool are root.
1966 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao5377d792020-07-16 17:37:39 +08001967 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001968 if (!DropRootUser()) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001969 return Dumpstate::RunStatus::ERROR;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001970 }
1971
Nandana Dutt5c390032019-03-12 10:52:56 +00001972 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttdb379fa2019-10-09 16:54:41 +01001973 Dumpstate::RunStatus status = dumpstate();
1974 // Capture logcat since the last time we did it.
1975 DoSystemLogcat(logcat_ts);
1976 return status;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001977}
1978
Rhed Jaob5685b32020-08-14 17:19:17 +08001979// Common states for telephony and wifi which are needed to be collected before
1980// dumpstate drop the root user.
1981static void DumpstateRadioAsRoot() {
1982 DumpIpTablesAsRoot();
1983 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1984}
1985
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001986// This method collects common dumpsys for telephony and wifi. Typically, wifi
1987// reports are fine to include all information, but telephony reports on user
1988// builds need to strip some content (see DumpstateTelephonyOnly).
1989static void DumpstateRadioCommon(bool include_sensitive_info = true) {
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001990 // We need to be picky about some stuff for telephony reports on user builds.
1991 if (!include_sensitive_info) {
1992 // Only dump the radio log buffer (other buffers and dumps contain too much unrelated info).
1993 DoRadioLogcat();
1994 } else {
Rhed Jaob5685b32020-08-14 17:19:17 +08001995 // DumpHals takes long time, post it to the another thread in the pool,
1996 // if pool is available.
Chris Morinbc223142022-02-04 14:17:11 -08001997 std::future<std::string> dump_hals;
Rhed Jaob5685b32020-08-14 17:19:17 +08001998 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001999 dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
Rhed Jaob5685b32020-08-14 17:19:17 +08002000 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002001 // Contains various system properties and process startup info.
2002 do_dmesg();
2003 // Logs other than the radio buffer may contain package/component names and potential PII.
2004 DoLogcat();
2005 // Too broad for connectivity problems.
2006 DoKmsg();
Rhed Jaob5685b32020-08-14 17:19:17 +08002007 // DumpHals contains unrelated hardware info (camera, NFC, biometrics, ...).
2008 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002009 WaitForTask(std::move(dump_hals));
Rhed Jaob5685b32020-08-14 17:19:17 +08002010 } else {
2011 RUN_SLOW_FUNCTION_AND_LOG(DUMP_HALS_TASK, DumpHals);
2012 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002013 }
2014
Jayachandran Ca94c7172017-06-10 15:08:12 -07002015 DumpPacketStats();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002016 DumpIpAddrAndRules();
2017 dump_route_tables();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002018 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
2019 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08002020}
2021
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002022// We use "telephony" here for legacy reasons, though this now really means "connectivity" (cellular
2023// + wifi + networking). This method collects dumpsys for connectivity debugging only. General rules
2024// for what can be included on user builds: all reported information MUST directly relate to
2025// connectivity debugging or customer support and MUST NOT contain unrelated personally identifiable
2026// information. This information MUST NOT identify user-installed packages (UIDs are OK, package
2027// names are not), and MUST NOT contain logs of user application traffic.
2028// TODO(b/148168577) rename this and other related fields/methods to "connectivity" instead.
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08002029static void DumpstateTelephonyOnly(const std::string& calling_package) {
mukesh agrawal253dad42018-01-23 21:59:59 -08002030 DurationReporter duration_reporter("DUMPSTATE");
Jichao Lie89d9c12019-11-21 19:02:51 -08002031
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002032 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
mukesh agrawal253dad42018-01-23 21:59:59 -08002033
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002034 const bool include_sensitive_info = !PropertiesHelper::IsUserBuild();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002035
Rhed Jaob5685b32020-08-14 17:19:17 +08002036 DumpstateRadioAsRoot();
2037 if (!DropRootUser()) {
2038 return;
2039 }
2040
2041 // Starts thread pool after the root user is dropped, and two additional threads
2042 // are created for DumpHals in the DumpstateRadioCommon and DumpstateBoard.
Chris Morinbc223142022-02-04 14:17:11 -08002043 std::future<std::string> dump_board;
Rhed Jaob5685b32020-08-14 17:19:17 +08002044 if (ds.dump_pool_) {
2045 ds.dump_pool_->start(/*thread_counts =*/2);
2046
2047 // DumpstateBoard takes long time, post it to the another thread in the pool,
2048 // if pool is available.
Chris Morinbc223142022-02-04 14:17:11 -08002049 dump_board = ds.dump_pool_->enqueueTaskWithFd(
2050 DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
Rhed Jaob5685b32020-08-14 17:19:17 +08002051 }
2052
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002053 DumpstateRadioCommon(include_sensitive_info);
2054
2055 if (include_sensitive_info) {
2056 // Contains too much unrelated PII, and given the unstructured nature of sysprops, we can't
2057 // really cherrypick all of the connectivity-related ones. Apps generally have no business
2058 // reading these anyway, and there should be APIs to supply the info in a more app-friendly
2059 // way.
2060 RunCommand("SYSTEM PROPERTIES", {"getprop"});
2061 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002062
2063 printf("========================================================\n");
2064 printf("== Android Framework Services\n");
2065 printf("========================================================\n");
2066
Vishnu Nair652cc802017-11-30 15:18:30 -08002067 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2068 SEC_TO_MSEC(10));
Hunter Knepshield31cbae12021-05-11 16:23:24 -07002069 RunDumpsys("DUMPSYS", {"vcn_management"}, CommandOptions::WithTimeout(90).Build(),
2070 SEC_TO_MSEC(10));
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08002071 if (include_sensitive_info) {
2072 // Carrier apps' services will be dumped below in dumpsys activity service all-non-platform.
2073 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
2074 SEC_TO_MSEC(10));
2075 } else {
2076 // If the caller is a carrier app and has a carrier service, dump it here since we aren't
2077 // running dumpsys activity service all-non-platform below. Due to the increased output, we
2078 // give a higher timeout as well.
2079 RunDumpsys("DUMPSYS", {"carrier_config", "--requesting-package", calling_package},
2080 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(30));
2081 }
2082 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002083 RunDumpsys("DUMPSYS", {"netpolicy"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2084 RunDumpsys("DUMPSYS", {"network_management"}, CommandOptions::WithTimeout(90).Build(),
Sooraj Sasindrane8d98912018-04-20 11:31:55 -07002085 SEC_TO_MSEC(10));
Hunter Knepshield0fe51b12020-03-05 16:58:20 -08002086 RunDumpsys("DUMPSYS", {"telephony.registry"}, CommandOptions::WithTimeout(90).Build(),
2087 SEC_TO_MSEC(10));
Jack Yu773cc032023-03-16 22:43:39 -07002088 RunDumpsys("DUMPSYS", {"isub"}, CommandOptions::WithTimeout(90).Build(),
2089 SEC_TO_MSEC(10));
Grant Menke56698972023-02-24 13:11:07 -08002090 RunDumpsys("DUMPSYS", {"telecom"}, CommandOptions::WithTimeout(90).Build(),
2091 SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002092 if (include_sensitive_info) {
2093 // Contains raw IP addresses, omit from reports on user builds.
2094 RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2095 // Contains raw destination IP/MAC addresses, omit from reports on user builds.
2096 RunDumpsys("DUMPSYS", {"connmetrics"}, CommandOptions::WithTimeout(90).Build(),
2097 SEC_TO_MSEC(10));
2098 // Contains package/component names, omit from reports on user builds.
2099 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
2100 SEC_TO_MSEC(10));
2101 // Contains package names, but should be relatively simple to remove them (also contains
2102 // UIDs already), omit from reports on user builds.
2103 RunDumpsys("BATTERYSTATS", {"deviceidle"}, CommandOptions::WithTimeout(90).Build(),
2104 SEC_TO_MSEC(10));
2105 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002106
2107 printf("========================================================\n");
2108 printf("== Running Application Services\n");
2109 printf("========================================================\n");
2110
2111 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
2112
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002113 if (include_sensitive_info) {
2114 printf("========================================================\n");
2115 printf("== Running Application Services (non-platform)\n");
2116 printf("========================================================\n");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002117
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002118 // Contains package/component names and potential PII, omit from reports on user builds.
2119 // To get dumps of the active CarrierService(s) on user builds, we supply an argument to the
2120 // carrier_config dumpsys instead.
2121 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
2122 DUMPSYS_COMPONENTS_OPTIONS);
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002123
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002124 printf("========================================================\n");
2125 printf("== Checkins\n");
2126 printf("========================================================\n");
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002127
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002128 // Contains package/component names, omit from reports on user builds.
2129 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
2130 }
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002131
2132 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07002133 printf("== dumpstate: done (id %d)\n", ds.id_);
2134 printf("========================================================\n");
Rhed Jaob5685b32020-08-14 17:19:17 +08002135
2136 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002137 WaitForTask(std::move(dump_board));
Rhed Jaob5685b32020-08-14 17:19:17 +08002138 } else {
2139 RUN_SLOW_FUNCTION_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
2140 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002141}
2142
mukesh agrawal253dad42018-01-23 21:59:59 -08002143// This method collects dumpsys for wifi debugging only
2144static void DumpstateWifiOnly() {
2145 DurationReporter duration_reporter("DUMPSTATE");
2146
Rhed Jaob5685b32020-08-14 17:19:17 +08002147 DumpstateRadioAsRoot();
2148 if (!DropRootUser()) {
2149 return;
2150 }
2151
2152 // Starts thread pool after the root user is dropped. Only one additional
2153 // thread is needed for DumpHals in the DumpstateRadioCommon.
2154 if (ds.dump_pool_) {
2155 ds.dump_pool_->start(/*thread_counts =*/1);
2156 }
2157
mukesh agrawal253dad42018-01-23 21:59:59 -08002158 DumpstateRadioCommon();
2159
2160 printf("========================================================\n");
2161 printf("== Android Framework Services\n");
2162 printf("========================================================\n");
2163
2164 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2165 SEC_TO_MSEC(10));
2166 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
2167 SEC_TO_MSEC(10));
2168
2169 printf("========================================================\n");
2170 printf("== dumpstate: done (id %d)\n", ds.id_);
2171 printf("========================================================\n");
2172}
2173
Elis Elliott8e401ad2023-08-08 11:18:59 +00002174// Collects a lightweight dumpstate to be used for debugging onboarding related flows.
2175static void DumpstateOnboardingOnly() {
2176 ds.AddDir(LOGPERSIST_DATA_DIR, false);
2177}
2178
Nandana Duttcf419a72019-03-14 10:40:17 +00002179Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
Gavin Corkery789d7a52021-02-24 23:52:35 +00002180 const std::string temp_file_pattern = ds.bugreport_internal_dir_ + "/dumptrace_XXXXXX";
Nandana Duttfaafd522019-03-11 09:23:09 +00002181 const size_t buf_size = temp_file_pattern.length() + 1;
2182 std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
2183 memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
2184
2185 // Create a new, empty file to receive all trace dumps.
2186 //
2187 // TODO: This can be simplified once we remove support for the old style
2188 // dumps. We can have a file descriptor passed in to dump_traces instead
2189 // of creating a file, closing it and then reopening it again.
2190 android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
2191 if (fd < 0) {
2192 MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002193 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002194 }
2195
2196 // Nobody should have access to this temporary file except dumpstate, but we
2197 // temporarily grant 'read' to 'others' here because this file is created
2198 // when tombstoned is still running as root, but dumped after dropping. This
2199 // can go away once support for old style dumping has.
2200 const int chmod_ret = fchmod(fd, 0666);
2201 if (chmod_ret < 0) {
2202 MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002203 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002204 }
2205
2206 std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
2207 if (proc.get() == nullptr) {
2208 MYLOGE("opendir /proc failed: %s\n", strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002209 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002210 }
2211
2212 // Number of times process dumping has timed out. If we encounter too many
2213 // failures, we'll give up.
2214 int timeout_failures = 0;
2215 bool dalvik_found = false;
2216
Jayant Chowdharya0a8eb22022-05-20 03:30:09 +00002217 const std::set<int> hal_pids = get_interesting_pids();
Nandana Duttfaafd522019-03-11 09:23:09 +00002218
2219 struct dirent* d;
2220 while ((d = readdir(proc.get()))) {
Nandana Duttcf419a72019-03-14 10:40:17 +00002221 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttfaafd522019-03-11 09:23:09 +00002222 int pid = atoi(d->d_name);
2223 if (pid <= 0) {
2224 continue;
2225 }
2226
Kevin Jeond0f8a982023-04-07 14:27:11 -04002227 // Skip cached processes.
2228 if (IsCached(pid)) {
2229 // For consistency, the header and footer to this message match those
2230 // dumped by debuggerd in the success case.
2231 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
2232 dprintf(fd, "Dump skipped for cached process.\n");
2233 dprintf(fd, "---- end %d ----", pid);
2234 continue;
2235 }
2236
Nandana Duttfaafd522019-03-11 09:23:09 +00002237 const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
2238 std::string exe;
2239 if (!android::base::Readlink(link_name, &exe)) {
2240 continue;
2241 }
2242
2243 bool is_java_process;
2244 if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
2245 // Don't bother dumping backtraces for the zygote.
2246 if (IsZygote(pid)) {
2247 continue;
2248 }
2249
2250 dalvik_found = true;
2251 is_java_process = true;
2252 } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
2253 is_java_process = false;
2254 } else {
2255 // Probably a native process we don't care about, continue.
2256 continue;
2257 }
2258
2259 // If 3 backtrace dumps fail in a row, consider debuggerd dead.
2260 if (timeout_failures == 3) {
2261 dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
2262 break;
2263 }
2264
2265 const uint64_t start = Nanotime();
2266 const int ret = dump_backtrace_to_file_timeout(
Kevin Jeonb8a39362023-04-04 15:00:34 -04002267 pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace, 3, fd);
Nandana Duttfaafd522019-03-11 09:23:09 +00002268
2269 if (ret == -1) {
2270 // For consistency, the header and footer to this message match those
2271 // dumped by debuggerd in the success case.
2272 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
2273 dprintf(fd, "Dump failed, likely due to a timeout.\n");
2274 dprintf(fd, "---- end %d ----", pid);
2275 timeout_failures++;
2276 continue;
2277 }
2278
2279 // We've successfully dumped stack traces, reset the failure count
2280 // and write a summary of the elapsed time to the file and continue with the
2281 // next process.
2282 timeout_failures = 0;
2283
2284 dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
2285 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
2286 }
2287
2288 if (!dalvik_found) {
2289 MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
2290 }
2291
Nandana Duttcf419a72019-03-14 10:40:17 +00002292 *path = file_name_buf.release();
2293 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002294}
2295
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002296static dumpstate_hal_hidl::DumpstateMode GetDumpstateHalModeHidl(
2297 const Dumpstate::BugreportMode bugreport_mode) {
2298 switch (bugreport_mode) {
2299 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2300 return dumpstate_hal_hidl::DumpstateMode::FULL;
2301 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2302 return dumpstate_hal_hidl::DumpstateMode::INTERACTIVE;
2303 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2304 return dumpstate_hal_hidl::DumpstateMode::REMOTE;
2305 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2306 return dumpstate_hal_hidl::DumpstateMode::WEAR;
2307 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2308 return dumpstate_hal_hidl::DumpstateMode::CONNECTIVITY;
2309 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2310 return dumpstate_hal_hidl::DumpstateMode::WIFI;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002311 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002312 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2313 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2314 }
2315 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2316}
2317
2318static dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode GetDumpstateHalModeAidl(
2319 const Dumpstate::BugreportMode bugreport_mode) {
2320 switch (bugreport_mode) {
2321 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2322 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::FULL;
2323 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2324 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::INTERACTIVE;
2325 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2326 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::REMOTE;
2327 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2328 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WEAR;
2329 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2330 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::CONNECTIVITY;
2331 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2332 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WIFI;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002333 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002334 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2335 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2336 }
2337 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2338}
2339
2340static void DoDumpstateBoardHidl(
2341 const sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_1_0,
2342 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2343 const Dumpstate::BugreportMode bugreport_mode,
2344 const size_t timeout_sec) {
2345
2346 using ScopedNativeHandle =
2347 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
2348 ScopedNativeHandle handle(native_handle_create(static_cast<int>(dumpstate_fds.size()), 0),
2349 [](native_handle_t* handle) {
2350 // we don't close file handle's here
2351 // via native_handle_close(handle)
2352 // instead we let dumpstate_fds close the file handles when
2353 // dumpstate_fds gets destroyed
2354 native_handle_delete(handle);
2355 });
2356 if (handle == nullptr) {
2357 MYLOGE("Could not create native_handle for dumpstate HAL\n");
2358 return;
2359 }
2360
2361 for (size_t i = 0; i < dumpstate_fds.size(); i++) {
2362 handle.get()->data[i] = dumpstate_fds[i].get();
2363 }
2364
2365 // Prefer version 1.1 if available. New devices launching with R are no longer allowed to
2366 // implement just 1.0.
2367 const char* descriptor_to_kill;
2368 using DumpstateBoardTask = std::packaged_task<bool()>;
2369 DumpstateBoardTask dumpstate_board_task;
2370 sp<dumpstate_hal_hidl::IDumpstateDevice> dumpstate_hal(
2371 dumpstate_hal_hidl::IDumpstateDevice::castFrom(dumpstate_hal_1_0));
2372 if (dumpstate_hal != nullptr) {
2373 MYLOGI("Using IDumpstateDevice v1.1 HIDL HAL");
2374
2375 dumpstate_hal_hidl::DumpstateMode dumpstate_hal_mode =
2376 GetDumpstateHalModeHidl(bugreport_mode);
2377
2378 descriptor_to_kill = dumpstate_hal_hidl::IDumpstateDevice::descriptor;
2379 dumpstate_board_task =
2380 DumpstateBoardTask([timeout_sec, dumpstate_hal_mode, dumpstate_hal, &handle]() -> bool {
2381 ::android::hardware::Return<dumpstate_hal_hidl::DumpstateStatus> status =
2382 dumpstate_hal->dumpstateBoard_1_1(handle.get(), dumpstate_hal_mode,
2383 SEC_TO_MSEC(timeout_sec));
2384 if (!status.isOk()) {
2385 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2386 return false;
2387 } else if (status != dumpstate_hal_hidl::DumpstateStatus::OK) {
2388 MYLOGE("dumpstateBoard failed with DumpstateStatus::%s\n",
2389 dumpstate_hal_hidl::toString(status).c_str());
2390 return false;
2391 }
2392 return true;
2393 });
2394 } else {
2395 MYLOGI("Using IDumpstateDevice v1.0 HIDL HAL");
2396
2397 descriptor_to_kill = dumpstate_hal_hidl_1_0::IDumpstateDevice::descriptor;
2398 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal_1_0, &handle]() -> bool {
2399 ::android::hardware::Return<void> status =
2400 dumpstate_hal_1_0->dumpstateBoard(handle.get());
2401 if (!status.isOk()) {
2402 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2403 return false;
2404 }
2405 return true;
2406 });
2407 }
2408 auto result = dumpstate_board_task.get_future();
2409 std::thread(std::move(dumpstate_board_task)).detach();
2410
2411 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2412 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2413 if (!android::base::SetProperty(
2414 "ctl.interface_restart",
2415 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2416 MYLOGE("Couldn't restart dumpstate HAL\n");
2417 }
2418 }
2419 // Wait some time for init to kill dumpstate vendor HAL
2420 constexpr size_t killing_timeout_sec = 10;
2421 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2422 MYLOGE(
2423 "killing dumpstateBoard timed out after %zus, continue and "
2424 "there might be racing in content\n",
2425 killing_timeout_sec);
2426 }
2427}
2428
2429static void DoDumpstateBoardAidl(
2430 const std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal,
2431 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2432 const Dumpstate::BugreportMode bugreport_mode, const size_t timeout_sec) {
2433 MYLOGI("Using IDumpstateDevice AIDL HAL");
2434
2435 const char* descriptor_to_kill;
2436 using DumpstateBoardTask = std::packaged_task<bool()>;
2437 DumpstateBoardTask dumpstate_board_task;
2438 dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode dumpstate_hal_mode =
2439 GetDumpstateHalModeAidl(bugreport_mode);
2440
2441 descriptor_to_kill = dumpstate_hal_aidl::IDumpstateDevice::descriptor;
2442 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal, &dumpstate_fds, dumpstate_hal_mode,
2443 timeout_sec]() -> bool {
2444 auto status = dumpstate_hal->dumpstateBoard(dumpstate_fds, dumpstate_hal_mode, timeout_sec);
2445
2446 if (!status.isOk()) {
2447 MYLOGE("dumpstateBoard failed: %s\n", status.getDescription().c_str());
2448 return false;
2449 }
2450 return true;
2451 });
2452 auto result = dumpstate_board_task.get_future();
2453 std::thread(std::move(dumpstate_board_task)).detach();
2454
2455 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2456 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2457 if (!android::base::SetProperty(
2458 "ctl.interface_restart",
2459 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2460 MYLOGE("Couldn't restart dumpstate HAL\n");
2461 }
2462 }
2463 // Wait some time for init to kill dumpstate vendor HAL
2464 constexpr size_t killing_timeout_sec = 10;
2465 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2466 MYLOGE(
2467 "killing dumpstateBoard timed out after %zus, continue and "
2468 "there might be racing in content\n",
2469 killing_timeout_sec);
2470 }
2471}
2472
2473static std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> GetDumpstateBoardAidlService() {
2474 const std::string aidl_instance_name =
2475 std::string(dumpstate_hal_aidl::IDumpstateDevice::descriptor) + "/default";
2476
2477 if (!AServiceManager_isDeclared(aidl_instance_name.c_str())) {
2478 return nullptr;
2479 }
2480
2481 ndk::SpAIBinder dumpstateBinder(AServiceManager_waitForService(aidl_instance_name.c_str()));
2482
2483 return dumpstate_hal_aidl::IDumpstateDevice::fromBinder(dumpstateBinder);
2484}
2485
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002486void Dumpstate::DumpstateBoard(int out_fd) {
2487 dprintf(out_fd, "========================================================\n");
2488 dprintf(out_fd, "== Board\n");
2489 dprintf(out_fd, "========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08002490
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002491 /*
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002492 * mount debugfs for non-user builds with ro.product.debugfs_restrictions.enabled
Hridya Valsaraju51101602021-04-02 14:32:46 -07002493 * set to true and unmount it after invoking dumpstateBoard_* methods.
2494 * This is to enable debug builds to not have debugfs mounted during runtime.
2495 * It will also ensure that debugfs is only accessed by the dumpstate HAL.
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002496 */
Hridya Valsaraju51101602021-04-02 14:32:46 -07002497 auto mount_debugfs =
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002498 android::base::GetBoolProperty("ro.product.debugfs_restrictions.enabled", false);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002499 if (mount_debugfs) {
2500 RunCommand("mount debugfs", {"mount", "-t", "debugfs", "debugfs", "/sys/kernel/debug"},
2501 AS_ROOT_20);
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002502 RunCommand("chmod debugfs", {"chmod", "0755", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002503 }
2504
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002505 std::vector<std::string> paths;
2506 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07002507 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002508 paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
2509 kDumpstateBoardFiles[i].c_str()));
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002510 remover.emplace_back(android::base::make_scope_guard(
2511 std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002512 }
Jie Song9fbfad02017-06-20 16:29:42 -07002513
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002514 // get dumpstate HAL AIDL implementation
2515 std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal_handle_aidl(
2516 GetDumpstateBoardAidlService());
2517 if (dumpstate_hal_handle_aidl == nullptr) {
2518 MYLOGI("No IDumpstateDevice AIDL implementation\n");
2519 }
2520
2521 // get dumpstate HAL HIDL implementation, only if AIDL HAL implementation not found
2522 sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_handle_hidl_1_0 = nullptr;
2523 if (dumpstate_hal_handle_aidl == nullptr) {
2524 dumpstate_hal_handle_hidl_1_0 = dumpstate_hal_hidl_1_0::IDumpstateDevice::getService();
2525 if (dumpstate_hal_handle_hidl_1_0 == nullptr) {
2526 MYLOGI("No IDumpstateDevice HIDL implementation\n");
2527 }
2528 }
2529
2530 // if neither HIDL nor AIDL implementation found, then return
2531 if (dumpstate_hal_handle_hidl_1_0 == nullptr && dumpstate_hal_handle_aidl == nullptr) {
2532 MYLOGE("Could not find IDumpstateDevice implementation\n");
Wei Wang587eac92018-04-05 12:17:20 -07002533 return;
2534 }
2535
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002536 // this is used to hold the file descriptors and when this variable goes out of scope
2537 // the file descriptors are closed
2538 std::vector<::ndk::ScopedFileDescriptor> dumpstate_fds;
Wei Wang587eac92018-04-05 12:17:20 -07002539
Nandana Dutt5c390032019-03-12 10:52:56 +00002540 // TODO(128270426): Check for consent in between?
Wei Wang587eac92018-04-05 12:17:20 -07002541 for (size_t i = 0; i < paths.size(); i++) {
2542 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
2543
2544 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
2545 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
2546 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
2547 if (fd < 0) {
2548 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
2549 return;
2550 }
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002551
2552 dumpstate_fds.emplace_back(fd.release());
2553 // we call fd.release() here to make sure "fd" does not get closed
2554 // after "fd" goes out of scope after this block.
2555 // "fd" will be closed when "dumpstate_fds" goes out of scope
2556 // i.e. when we exit this function
Wei Wang587eac92018-04-05 12:17:20 -07002557 }
2558
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002559 // Given that bugreport is required to diagnose failures, it's better to set an arbitrary amount
2560 // of timeout for IDumpstateDevice than to block the rest of bugreport. In the timeout case, we
2561 // will kill the HAL and grab whatever it dumped in time.
Michael Eastwood8523ea02022-03-10 16:33:08 -08002562 constexpr size_t timeout_sec = 45;
Wei Wang587eac92018-04-05 12:17:20 -07002563
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002564 if (dumpstate_hal_handle_aidl != nullptr) {
2565 DoDumpstateBoardAidl(dumpstate_hal_handle_aidl, dumpstate_fds, options_->bugreport_mode,
2566 timeout_sec);
2567 } else if (dumpstate_hal_handle_hidl_1_0 != nullptr) {
2568 // run HIDL HAL only if AIDL HAL not found
2569 DoDumpstateBoardHidl(dumpstate_hal_handle_hidl_1_0, dumpstate_fds, options_->bugreport_mode,
2570 timeout_sec);
Wei Wang587eac92018-04-05 12:17:20 -07002571 }
2572
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002573 if (mount_debugfs) {
Hridya Valsaraju51101602021-04-02 14:32:46 -07002574 auto keep_debugfs_mounted =
2575 android::base::GetProperty("persist.dbg.keep_debugfs_mounted", "");
2576 if (keep_debugfs_mounted.empty())
2577 RunCommand("unmount debugfs", {"umount", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002578 }
2579
Wei Wang587eac92018-04-05 12:17:20 -07002580 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
2581 for (size_t i = 0; i < paths.size(); i++) {
2582 struct stat s;
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002583 if (fstat(dumpstate_fds[i].get(), &s) == -1) {
2584 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(), strerror(errno));
Wei Wang587eac92018-04-05 12:17:20 -07002585 file_sizes[i] = -1;
2586 continue;
2587 }
2588 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002589 }
2590
2591 for (size_t i = 0; i < paths.size(); i++) {
2592 if (file_sizes[i] == -1) {
2593 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002594 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002595 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07002596 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002597 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002598 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002599 remover[i].Disable();
2600 EnqueueAddZipEntryAndCleanupIfNeeded(kDumpstateBoardFiles[i], paths[i]);
2601 dprintf(out_fd, "*** See %s entry ***\n", kDumpstateBoardFiles[i].c_str());
Jie Song9fbfad02017-06-20 16:29:42 -07002602 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08002603}
2604
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002605static void ShowUsage() {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002606 fprintf(stderr,
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002607 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o directory] [-p] "
2608 "[-s] [-S] [-q] [-P] [-R] [-L] [-V version]\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002609 " -h: display this help message\n"
2610 " -b: play sound file instead of vibrate, at beginning of job\n"
2611 " -e: play sound file instead of vibrate, at end of job\n"
mhasank2d75c442020-06-11 15:05:25 -07002612 " -o: write to custom directory (only in limited mode)\n"
Abhijeet Kaurbb55a3b2019-06-13 18:07:25 +01002613 " -p: capture screenshot to filename.png\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002614 " -s: write zipped file to control socket (for init)\n"
2615 " -S: write file location to control socket (for init)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002616 " -q: disable vibrate\n"
Abhijeet Kaure370d682019-10-01 16:49:30 +01002617 " -P: send broadcast when started and do progress updates\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002618 " -R: take bugreport in remote mode (shouldn't be used with -P)\n"
Nandana Dutt235864b2019-01-22 12:10:16 +00002619 " -w: start binder service and make it wait for a call to startBugreport\n"
mhasankd451a472020-05-26 18:02:39 -07002620 " -L: output limited information that is safe for submission in feedback reports\n"
Felipe Lemed071c682016-10-20 16:48:00 -07002621 " -v: prints the dumpstate header and exit\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002622}
2623
Wei Liuf87959e2016-08-26 14:51:42 -07002624static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07002625 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07002626}
2627
Felipe Leme1d486fe2016-10-14 18:06:47 -07002628bool Dumpstate::FinishZipFile() {
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002629 // Runs all enqueued adding zip entry and cleanup tasks before finishing the zip file.
2630 if (zip_entry_tasks_) {
2631 zip_entry_tasks_->run(/* do_cancel = */false);
2632 }
2633
Felipe Leme9a523ae2016-10-20 15:10:33 -07002634 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07002635 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07002636 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002637 // Final timestamp
2638 char date[80];
2639 time_t the_real_now_please_stand_up = time(nullptr);
2640 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002641 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002642 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002643
Felipe Leme9a523ae2016-10-20 15:10:33 -07002644 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002645 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08002646 return false;
2647 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07002648 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002649 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08002650 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08002651 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08002652
Felipe Leme0f3fb202016-06-10 17:10:53 -07002653 // Add log file (which contains stderr output) to zip...
2654 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002655 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07002656 MYLOGE("Failed to add dumpstate log to .zip file\n");
2657 return false;
2658 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002659 // TODO: Should truncate the existing file.
2660 // ... and re-open it for further logging.
Nandana Dutta344cb62019-02-22 15:12:35 +00002661 if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
2662 return false;
2663 }
Felipe Leme0f3fb202016-06-10 17:10:53 -07002664 fprintf(stderr, "\n");
2665
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002666 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07002667 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002668 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002669 return false;
2670 }
2671
Felipe Leme1d486fe2016-10-14 18:06:47 -07002672 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
2673 ds.zip_file.reset(nullptr);
2674
Felipe Lemee9d2c542016-11-15 11:48:26 -08002675 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002676 android::os::UnlinkAndLogOnError(tmp_path_);
Felipe Lemec4eee562016-04-21 15:42:55 -07002677
Felipe Leme1e9edc62015-12-21 16:02:13 -08002678 return true;
2679}
Felipe Leme6e01fa62015-11-11 19:35:14 -08002680
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00002681static void SendBroadcast(const std::string& action,
2682 const std::vector<std::string>& args,
2683 int32_t user_id) {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002684 // clang-format off
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00002685 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user",
2686 std::to_string(user_id), "--receiver-foreground",
2687 "--receiver-include-background", "-a", action};
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002688 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08002689
2690 am.insert(am.end(), args.begin(), args.end());
2691
Felipe Leme8d2410e2017-02-08 09:46:08 -08002692 RunCommand("", am,
2693 CommandOptions::WithTimeout(20)
2694 .Log("Sending broadcast: '%s'\n")
2695 .Always()
2696 .DropRoot()
2697 .RedirectStderr()
2698 .Build());
2699}
2700
Felipe Leme35b8cf12017-02-10 15:47:29 -08002701static void Vibrate(int duration_ms) {
2702 // clang-format off
Lais Andrade51156962021-02-22 19:21:35 +00002703 std::vector<std::string> args = {"cmd", "vibrator_manager", "synced", "-f", "-d", "dumpstate",
2704 "oneshot", std::to_string(duration_ms)};
2705 RunCommand("", args,
Felipe Leme35b8cf12017-02-10 15:47:29 -08002706 CommandOptions::WithTimeout(10)
2707 .Log("Vibrate: '%s'\n")
2708 .Always()
2709 .Build());
2710 // clang-format on
2711}
2712
Nandana Dutt979388e2018-11-30 16:48:55 +00002713static void MaybeResolveSymlink(std::string* path) {
2714 std::string resolved_path;
2715 if (android::base::Readlink(*path, &resolved_path)) {
2716 *path = resolved_path;
2717 }
2718}
2719
Nandana Dutt4be45d12018-09-26 15:04:23 +01002720/*
2721 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002722 * and adds the version file. Return false if zip_file could not be open to write.
Nandana Dutt4be45d12018-09-26 15:04:23 +01002723 */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002724static bool PrepareToWriteToFile() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002725 MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2726
Nandana Dutt4be45d12018-09-26 15:04:23 +01002727 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2728 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002729 ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002730 char date[80];
2731 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2732 ds.name_ = date;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002733
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002734 if (ds.options_->telephony_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002735 ds.base_name_ += "-telephony";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002736 } else if (ds.options_->wifi_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002737 ds.base_name_ += "-wifi";
2738 }
2739
Paul Chang0d2aad72020-02-13 20:04:03 +08002740 if (ds.options_->do_screenshot) {
Nandana Dutt9d17b942020-03-26 10:02:59 +00002741 ds.screenshot_path_ = ds.GetPath(ds.CalledByApi() ? "-png.tmp" : ".png");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002742 }
2743 ds.tmp_path_ = ds.GetPath(".tmp");
2744 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2745
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01002746 std::string destination = ds.CalledByApi()
Nandana Dutt54dbd672019-01-11 12:58:05 +00002747 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
Nandana Dutt9a76d202019-01-21 15:56:48 +00002748 : ds.bugreport_internal_dir_.c_str();
Nandana Dutt4be45d12018-09-26 15:04:23 +01002749 MYLOGD(
Nandana Dutt235c6672019-11-14 15:22:32 +00002750 "Bugreport dir: [%s] "
2751 "Base name: [%s] "
2752 "Suffix: [%s] "
2753 "Log path: [%s] "
2754 "Temporary path: [%s] "
2755 "Screenshot path: [%s]\n",
Nandana Dutt9a76d202019-01-21 15:56:48 +00002756 destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2757 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002758
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002759 ds.path_ = ds.GetPath(ds.CalledByApi() ? "-zip.tmp" : ".zip");
2760 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2761 create_parent_dirs(ds.path_.c_str());
2762 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2763 if (ds.zip_file == nullptr) {
2764 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2765 return false;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002766 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002767 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2768 ds.AddTextZipEntry("version.txt", ds.version_);
2769 return true;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002770}
2771
2772/*
Abhijeet Kaure370d682019-10-01 16:49:30 +01002773 * Finalizes writing to the file by zipping the tmp file to the final location,
Nandana Dutt4be45d12018-09-26 15:04:23 +01002774 * printing zipped file status, etc.
2775 */
2776static void FinalizeFile() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002777 bool do_text_file = !ds.FinishZipFile();
2778 if (do_text_file) {
2779 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002780 }
mhasank2d75c442020-06-11 15:05:25 -07002781
2782 std::string final_path = ds.path_;
2783 if (ds.options_->OutputToCustomFile()) {
mhasank3a4cfb42020-06-15 18:06:43 -07002784 final_path = ds.GetPath(ds.options_->out_dir, ".zip");
mhasank2d75c442020-06-11 15:05:25 -07002785 android::os::CopyFileToFile(ds.path_, final_path);
2786 }
2787
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002788 if (ds.options_->stream_to_socket) {
2789 android::os::CopyFileToFd(ds.path_, ds.control_socket_fd_);
2790 } else if (ds.options_->progress_updates_to_socket) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002791 if (do_text_file) {
2792 dprintf(ds.control_socket_fd_,
2793 "FAIL:could not create zip file, check %s "
2794 "for more details\n",
2795 ds.log_path_.c_str());
2796 } else {
mhasank2d75c442020-06-11 15:05:25 -07002797 dprintf(ds.control_socket_fd_, "OK:%s\n", final_path.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002798 }
2799 }
2800}
2801
Nandana Dutt4be45d12018-09-26 15:04:23 +01002802
Nandana Dutt58d72e22018-11-16 10:30:48 +00002803static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2804 switch (mode) {
2805 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2806 return "BUGREPORT_FULL";
2807 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2808 return "BUGREPORT_INTERACTIVE";
2809 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2810 return "BUGREPORT_REMOTE";
2811 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2812 return "BUGREPORT_WEAR";
2813 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2814 return "BUGREPORT_TELEPHONY";
2815 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2816 return "BUGREPORT_WIFI";
Elis Elliott8e401ad2023-08-08 11:18:59 +00002817 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
2818 return "BUGREPORT_ONBOARDING";
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002819 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2820 return "BUGREPORT_DEFAULT";
Nandana Dutt58d72e22018-11-16 10:30:48 +00002821 }
2822}
2823
Steven Leeb573eb82022-11-29 22:31:35 +08002824static bool IsConsentlessBugreportAllowed(const Dumpstate::DumpOptions& options) {
2825 // only BUGREPORT_TELEPHONY does not allow using consentless bugreport
2826 return !options.telephony_only;
2827}
2828
Paul Changf59c2b72020-03-10 02:08:55 +08002829static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options,
2830 bool is_screenshot_requested) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002831 // Modify com.android.shell.BugreportProgressService#isDefaultScreenshotRequired as well for
2832 // default system screenshots.
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002833 options->bugreport_mode = mode;
2834 options->bugreport_mode_string = ModeToString(mode);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002835 switch (mode) {
2836 case Dumpstate::BugreportMode::BUGREPORT_FULL:
Paul Changf59c2b72020-03-10 02:08:55 +08002837 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002838 break;
2839 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002840 // Currently, the dumpstate binder is only used by Shell to update progress.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002841 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002842 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002843 break;
2844 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002845 options->do_vibrate = false;
2846 options->is_remote_mode = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002847 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002848 break;
2849 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
Robert Ginda55ecebd2023-04-03 22:53:13 +00002850 options->do_vibrate = false;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002851 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002852 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002853 break;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002854 // TODO(b/148168577) rename TELEPHONY everywhere to CONNECTIVITY.
Nandana Dutt58d72e22018-11-16 10:30:48 +00002855 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002856 options->telephony_only = true;
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002857 options->do_progress_updates = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002858 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002859 break;
2860 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002861 options->wifi_only = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002862 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002863 break;
Elis Elliott8e401ad2023-08-08 11:18:59 +00002864 case Dumpstate::BugreportMode::BUGREPORT_ONBOARDING:
2865 options->onboarding_only = true;
2866 options->do_screenshot = false;
2867 break;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002868 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2869 break;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002870 }
2871}
2872
Nandana Dutt58d72e22018-11-16 10:30:48 +00002873static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
Nandana Dutt235c6672019-11-14 15:22:32 +00002874 MYLOGI(
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002875 "do_vibrate: %d stream_to_socket: %d progress_updates_to_socket: %d do_screenshot: %d "
Rhed Jao25f50e02020-08-20 00:10:32 +08002876 "is_remote_mode: %d show_header_only: %d telephony_only: %d "
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002877 "wifi_only: %d do_progress_updates: %d fd: %d bugreport_mode: %s "
mhasankd451a472020-05-26 18:02:39 -07002878 "limited_only: %d args: %s\n",
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002879 options.do_vibrate, options.stream_to_socket, options.progress_updates_to_socket,
Paul Chang0d2aad72020-02-13 20:04:03 +08002880 options.do_screenshot, options.is_remote_mode, options.show_header_only,
Rhed Jao25f50e02020-08-20 00:10:32 +08002881 options.telephony_only, options.wifi_only,
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002882 options.do_progress_updates, options.bugreport_fd.get(),
2883 options.bugreport_mode_string.c_str(),
2884 options.limited_only, options.args.c_str());
Nandana Dutt58d72e22018-11-16 10:30:48 +00002885}
2886
Nandana Dutt54dbd672019-01-11 12:58:05 +00002887void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
Kean Mariotti306633e2022-09-05 16:30:47 +00002888 int bugreport_flags,
Nandana Dutt54dbd672019-01-11 12:58:05 +00002889 const android::base::unique_fd& bugreport_fd_in,
Paul Changf59c2b72020-03-10 02:08:55 +08002890 const android::base::unique_fd& screenshot_fd_in,
2891 bool is_screenshot_requested) {
Kean Mariotti306633e2022-09-05 16:30:47 +00002892 this->use_predumped_ui_data = bugreport_flags & BugreportFlag::BUGREPORT_USE_PREDUMPED_UI_DATA;
Gavin Corkerya44686c2022-11-23 18:16:51 +00002893 this->is_consent_deferred = bugreport_flags & BugreportFlag::BUGREPORT_FLAG_DEFER_CONSENT;
Nandana Dutt54dbd672019-01-11 12:58:05 +00002894 // Duplicate the fds because the passed in fds don't outlive the binder transaction.
Todd Frederick621533f2022-03-26 02:54:17 +00002895 bugreport_fd.reset(fcntl(bugreport_fd_in.get(), F_DUPFD_CLOEXEC, 0));
2896 screenshot_fd.reset(fcntl(screenshot_fd_in.get(), F_DUPFD_CLOEXEC, 0));
Nandana Dutt58d72e22018-11-16 10:30:48 +00002897
Paul Changf59c2b72020-03-10 02:08:55 +08002898 SetOptionsFromMode(bugreport_mode, this, is_screenshot_requested);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002899}
2900
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002901Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
2902 RunStatus status = RunStatus::OK;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002903 int c;
mhasankd451a472020-05-26 18:02:39 -07002904 while ((c = getopt(argc, argv, "dho:svqzpLPBRSV:w")) != -1) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002905 switch (c) {
2906 // clang-format off
mhasank3a4cfb42020-06-15 18:06:43 -07002907 case 'o': out_dir = optarg; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002908 case 's': stream_to_socket = true; break;
2909 case 'S': progress_updates_to_socket = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002910 case 'v': show_header_only = true; break;
2911 case 'q': do_vibrate = false; break;
Paul Chang0d2aad72020-02-13 20:04:03 +08002912 case 'p': do_screenshot = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002913 case 'P': do_progress_updates = true; break;
2914 case 'R': is_remote_mode = true; break;
mhasankd451a472020-05-26 18:02:39 -07002915 case 'L': limited_only = true; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002916 case 'V':
2917 case 'd':
2918 case 'z':
2919 // compatibility no-op
2920 break;
Nandana Dutt235864b2019-01-22 12:10:16 +00002921 case 'w':
2922 // This was already processed
2923 break;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002924 case 'h':
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002925 status = RunStatus::HELP;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002926 break;
2927 default:
2928 fprintf(stderr, "Invalid option: %c\n", c);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002929 status = RunStatus::INVALID_INPUT;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002930 break;
2931 // clang-format on
2932 }
2933 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08002934
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002935 for (int i = 0; i < argc; i++) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002936 args += argv[i];
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002937 if (i < argc - 1) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002938 args += " ";
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002939 }
2940 }
2941
2942 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
2943 optind = 1;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002944
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002945 return status;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002946}
2947
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002948bool Dumpstate::DumpOptions::ValidateOptions() const {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002949 if (bugreport_fd.get() != -1 && stream_to_socket) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002950 return false;
2951 }
2952
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002953 if ((progress_updates_to_socket || do_progress_updates) && stream_to_socket) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002954 return false;
2955 }
2956
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002957 if (is_remote_mode && (do_progress_updates || stream_to_socket)) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002958 return false;
2959 }
2960 return true;
2961}
2962
Nandana Dutt197661d2018-11-16 16:40:21 +00002963void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
2964 options_ = std::move(options);
2965}
2966
Abhijeet Kaura407fb82020-03-27 12:51:12 +00002967void Dumpstate::Initialize() {
2968 /* gets the sequential id */
2969 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
2970 id_ = ++last_id;
2971 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
2972}
2973
Nandana Duttd2f5f082019-01-18 17:13:52 +00002974Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
2975 Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
Gavin Corkerya44686c2022-11-23 18:16:51 +00002976 HandleRunStatus(status);
2977 return status;
2978}
2979
2980Dumpstate::RunStatus Dumpstate::Retrieve(int32_t calling_uid, const std::string& calling_package) {
2981 Dumpstate::RunStatus status = RetrieveInternal(calling_uid, calling_package);
2982 HandleRunStatus(status);
2983 return status;
2984}
2985
2986Dumpstate::RunStatus Dumpstate::RetrieveInternal(int32_t calling_uid,
2987 const std::string& calling_package) {
2988 consent_callback_ = new ConsentCallback();
2989 const String16 incidentcompanion("incidentcompanion");
2990 sp<android::IBinder> ics(
2991 defaultServiceManager()->checkService(incidentcompanion));
2992 android::String16 package(calling_package.c_str());
2993 if (ics != nullptr) {
2994 MYLOGD("Checking user consent via incidentcompanion service\n");
2995 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
2996 calling_uid, package, String16(), String16(),
2997 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
2998 } else {
2999 MYLOGD(
3000 "Unable to check user consent; incidentcompanion service unavailable\n");
3001 return RunStatus::USER_CONSENT_TIMED_OUT;
3002 }
3003 UserConsentResult consent_result = consent_callback_->getResult();
3004 int timeout_ms = 30 * 1000;
3005 while (consent_result == UserConsentResult::UNAVAILABLE &&
3006 consent_callback_->getElapsedTimeMs() < timeout_ms) {
3007 sleep(1);
3008 consent_result = consent_callback_->getResult();
3009 }
3010 if (consent_result == UserConsentResult::DENIED) {
3011 return RunStatus::USER_CONSENT_DENIED;
3012 }
3013 if (consent_result == UserConsentResult::UNAVAILABLE) {
3014 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3015 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3016 consent_callback_.get());
3017 return RunStatus::USER_CONSENT_TIMED_OUT;
3018 }
3019
3020 bool copy_succeeded =
3021 android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
3022 if (copy_succeeded) {
3023 android::os::UnlinkAndLogOnError(path_);
3024 }
3025 return copy_succeeded ? Dumpstate::RunStatus::OK
3026 : Dumpstate::RunStatus::ERROR;
3027}
3028
3029void Dumpstate::HandleRunStatus(Dumpstate::RunStatus status) {
3030 if (listener_ != nullptr) {
Nandana Duttbabf6c72019-01-15 14:11:12 +00003031 switch (status) {
3032 case Dumpstate::RunStatus::OK:
Gavin Corkerya44686c2022-11-23 18:16:51 +00003033 listener_->onFinished(path_.c_str());
Nandana Duttbabf6c72019-01-15 14:11:12 +00003034 break;
3035 case Dumpstate::RunStatus::HELP:
3036 break;
3037 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003038 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00003039 break;
3040 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003041 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
3042 break;
3043 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3044 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
3045 break;
3046 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
3047 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00003048 break;
3049 }
3050 }
Nandana Duttbabf6c72019-01-15 14:11:12 +00003051}
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003052void Dumpstate::Cancel() {
3053 CleanupTmpFiles();
3054 android::os::UnlinkAndLogOnError(log_path_);
3055 for (int i = 0; i < NUM_OF_DUMPS; i++) {
3056 android::os::UnlinkAndLogOnError(ds.bugreport_internal_dir_ + "/" +
3057 kDumpstateBoardFiles[i]);
3058 }
3059 tombstone_data_.clear();
3060 anr_data_.clear();
Woody Lin20767a92022-11-29 15:50:24 +08003061 shutdown_checkpoints_.clear();
Rhed Jao0daac912020-08-21 14:48:20 +08003062
3063 // Instead of shutdown the pool, we delete temporary files directly since
3064 // shutdown blocking the call.
3065 if (dump_pool_) {
3066 dump_pool_->deleteTempFiles();
3067 }
3068 if (zip_entry_tasks_) {
3069 zip_entry_tasks_->run(/*do_cancel =*/ true);
3070 }
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003071}
3072
Kean Mariotti306633e2022-09-05 16:30:47 +00003073void Dumpstate::PreDumpUiData() {
3074 MaybeSnapshotUiTraces();
3075}
3076
Nandana Dutt979388e2018-11-30 16:48:55 +00003077/*
3078 * Dumps relevant information to a bugreport based on the given options.
3079 *
3080 * The bugreport can be dumped to a file or streamed to a socket.
3081 *
3082 * How dumping to file works:
3083 * stdout is redirected to a temporary file. This will later become the main bugreport entry.
3084 * stderr is redirected a log file.
3085 *
3086 * The temporary bugreport is then populated via printfs, dumping contents of files and
3087 * output of commands to stdout.
3088 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003089 * A bunch of other files and dumps are added to the zip archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00003090 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003091 * The temporary bugreport file and the log file also get added to the archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00003092 *
mhasank2d75c442020-06-11 15:05:25 -07003093 * Bugreports are first generated in a local directory and later copied to the caller's fd
3094 * or directory if supplied.
Nandana Dutt979388e2018-11-30 16:48:55 +00003095 */
Nandana Duttd2f5f082019-01-18 17:13:52 +00003096Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
3097 const std::string& calling_package) {
Rhed Jao5377d792020-07-16 17:37:39 +08003098 DurationReporter duration_reporter("RUN INTERNAL", /* logcat_only = */true);
Nandana Dutt979388e2018-11-30 16:48:55 +00003099 LogDumpOptions(*options_);
Nandana Dutt197661d2018-11-16 16:40:21 +00003100 if (!options_->ValidateOptions()) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00003101 MYLOGE("Invalid options specified\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003102 return RunStatus::INVALID_INPUT;
3103 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003104 /* set as high priority, and protect from OOM killer */
3105 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003106
Felipe Lemed071c682016-10-20 16:48:00 -07003107 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07003108 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003109 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003110 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003111 } else {
3112 /* fallback to kernels <= 2.6.35 */
3113 oom_adj = fopen("/proc/self/oom_adj", "we");
3114 if (oom_adj) {
3115 fputs("-17", oom_adj);
3116 fclose(oom_adj);
3117 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003118 }
3119
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003120 if (version_ == VERSION_DEFAULT) {
3121 version_ = VERSION_CURRENT;
Michal Karpinski4db754f2015-12-11 18:04:32 +00003122 }
3123
Chris Morin5a50d482022-02-01 17:41:18 -08003124 if (version_ != VERSION_CURRENT) {
3125 MYLOGE("invalid version requested ('%s'); supported values are: ('%s', '%s')\n",
3126 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003127 return RunStatus::INVALID_INPUT;
Felipe Lemed071c682016-10-20 16:48:00 -07003128 }
3129
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003130 if (options_->show_header_only) {
3131 PrintHeader();
3132 return RunStatus::OK;
Felipe Lemed071c682016-10-20 16:48:00 -07003133 }
3134
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003135 MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n",
3136 calling_uid, calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003137
Felipe Leme7447d7c2016-11-03 18:12:22 -07003138 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003139 std::string stats_path =
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003140 android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003141 progress_.reset(new Progress(stats_path));
Felipe Leme7447d7c2016-11-03 18:12:22 -07003142
Sahana Raof35ed432019-07-12 10:47:52 +01003143 if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
3144 MYLOGE("Failed to acquire wake lock: %s\n", strerror(errno));
3145 } else {
3146 // Wake lock will be released automatically on process death
3147 MYLOGD("Wake lock acquired.\n");
3148 }
3149
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08003150 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07003151
Felipe Lemef0292972016-11-22 13:57:05 -08003152 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07003153 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
3154 }
3155
Kevin Jeonfa64e642023-07-27 11:36:41 -04003156 if (PropertiesHelper::IsStrictRun()) {
3157 MYLOGI(
3158 "Running on strict-run mode, which has shorter timeouts "
3159 "(to disable, call 'setprop dumpstate.strict_run false')\n");
3160 }
3161
Nandana Dutt235c6672019-11-14 15:22:32 +00003162 MYLOGI("dumpstate info: id=%d, args='%s', bugreport_mode= %s bugreport format version: %s\n",
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00003163 id_, options_->args.c_str(), options_->bugreport_mode_string.c_str(), version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08003164
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003165 do_early_screenshot_ = options_->do_progress_updates;
Felipe Lemee338bf62015-12-07 14:03:50 -08003166
Christopher Ferrised9354f2014-10-01 17:35:01 -07003167 // If we are going to use a socket, do it as early as possible
3168 // to avoid timeouts from bugreport.
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003169 if (options_->stream_to_socket || options_->progress_updates_to_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07003170 MYLOGD("Opening control socket\n");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003171 control_socket_fd_ = open_socket_fn_("dumpstate");
Nandana Dutta344cb62019-02-22 15:12:35 +00003172 if (control_socket_fd_ == -1) {
3173 return ERROR;
3174 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003175 if (options_->progress_updates_to_socket) {
3176 options_->do_progress_updates = 1;
3177 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07003178 }
3179
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003180 if (!PrepareToWriteToFile()) {
3181 return ERROR;
3182 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08003183
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003184 // Interactive, wear & telephony modes are default to true.
3185 // and may enable from cli option or when using control socket
3186 if (options_->do_progress_updates) {
3187 // clang-format off
3188 std::vector<std::string> am_args = {
3189 "--receiver-permission", "android.permission.DUMP",
3190 };
3191 // clang-format on
3192 // Send STARTED broadcast for apps that listen to bugreport generation events
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003193 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED",
3194 am_args, multiuser_get_user_id(calling_uid));
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003195 if (options_->progress_updates_to_socket) {
3196 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08003197 }
3198 }
3199
Nick Kralevichf3599b32016-01-25 15:05:16 -08003200 /* read /proc/cmdline before dropping root */
3201 FILE *cmdline = fopen("/proc/cmdline", "re");
3202 if (cmdline) {
3203 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
3204 fclose(cmdline);
3205 }
3206
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003207 if (options_->do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08003208 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05003209 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003210
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003211 if (zip_file != nullptr) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003212 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
3213 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003214 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08003215 }
3216 }
3217
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003218 int dup_stdout_fd;
3219 int dup_stderr_fd;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003220 // Redirect stderr to log_path_ for debugging.
3221 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
3222 if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
3223 return ERROR;
3224 }
3225 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
3226 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
3227 strerror(errno));
3228 }
Nandana Dutt979388e2018-11-30 16:48:55 +00003229
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003230 // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
3231 // moved into zip file later, if zipping.
3232 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
3233 // TODO: why not write to a file instead of stdout to overcome this problem?
3234 /* TODO: rather than generating a text file now and zipping it later,
3235 it would be more efficient to redirect stdout to the zip entry
3236 directly, but the libziparchive doesn't support that option yet. */
3237 if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
3238 return ERROR;
3239 }
3240 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
3241 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
3242 tmp_path_.c_str(), strerror(errno));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003243 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08003244
3245 // Don't buffer stdout
3246 setvbuf(stdout, nullptr, _IONBF, 0);
3247
Rhed Jao5377d792020-07-16 17:37:39 +08003248 // Enable the parallel run if the client requests to output to a file.
3249 EnableParallelRunIfNeeded();
3250 // Using scope guard to make sure the dump pool can be shut down correctly.
3251 auto scope_guard_to_shutdown_pool = android::base::make_scope_guard([=]() {
3252 ShutdownDumpPool();
3253 });
3254
Felipe Leme608385d2016-02-01 10:35:38 -08003255 // NOTE: there should be no stdout output until now, otherwise it would break the header.
3256 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08003257 // duration is logged into MYLOG instead.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003258 PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003259
Gavin Corkery6968f552020-11-22 18:09:05 +00003260 bool is_dumpstate_restricted = options_->telephony_only
3261 || options_->wifi_only
3262 || options_->limited_only;
3263 if (!is_dumpstate_restricted) {
Paul Chang0d2aad72020-02-13 20:04:03 +08003264 // Invoke critical dumpsys first to preserve system state, before doing anything else.
Jichao Lie89d9c12019-11-21 19:02:51 -08003265 RunDumpsysCritical();
Gavin Corkery6968f552020-11-22 18:09:05 +00003266 }
3267 MaybeTakeEarlyScreenshot();
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003268
3269 if (!is_dumpstate_restricted) {
3270 // Snapshot the system trace now (if running) to avoid that dumpstate's
3271 // own activity pushes out interesting data from the trace ring buffer.
3272 // The trace file is added to the zip by MaybeAddSystemTraceToZip().
3273 MaybeSnapshotSystemTrace();
Yohei Yukawa95305b32021-03-09 07:54:27 -08003274
Kean Mariotti306633e2022-09-05 16:30:47 +00003275 // Snapshot the UI traces now (if running).
3276 // The trace files will be added to bugreport later.
3277 MaybeSnapshotUiTraces();
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003278 }
Gavin Corkery6968f552020-11-22 18:09:05 +00003279 onUiIntensiveBugreportDumpsFinished(calling_uid);
3280 MaybeCheckUserConsent(calling_uid, calling_package);
3281 if (options_->telephony_only) {
3282 DumpstateTelephonyOnly(calling_package);
3283 } else if (options_->wifi_only) {
3284 DumpstateWifiOnly();
3285 } else if (options_->limited_only) {
3286 DumpstateLimitedOnly();
Elis Elliott8e401ad2023-08-08 11:18:59 +00003287 } else if (options_->onboarding_only) {
3288 DumpstateOnboardingOnly();
Gavin Corkery6968f552020-11-22 18:09:05 +00003289 } else {
Nandana Dutt4be45d12018-09-26 15:04:23 +01003290 // Dump state for the default case. This also drops root.
Jichao Lie89d9c12019-11-21 19:02:51 -08003291 RunStatus s = DumpstateDefaultAfterCritical();
Nandana Dutt5c390032019-03-12 10:52:56 +00003292 if (s != RunStatus::OK) {
Nandana Duttaac6f582019-07-26 14:32:47 +01003293 if (s == RunStatus::USER_CONSENT_DENIED) {
Nandana Dutt5c390032019-03-12 10:52:56 +00003294 HandleUserConsentDenied();
3295 }
3296 return s;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08003297 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07003298 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07003299
Felipe Leme55b42a62015-11-10 17:39:08 -08003300 /* close output if needed */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003301 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003302
Abhijeet Kaure370d682019-10-01 16:49:30 +01003303 // Zip the (now complete) .tmp file within the internal directory.
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003304 ATRACE_BEGIN("FinalizeFile");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003305 FinalizeFile();
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003306 ATRACE_END();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003307
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003308 // Share the final file with the caller if the user has consented or Shell is the caller.
Nandana Duttd2f5f082019-01-18 17:13:52 +00003309 Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
Gavin Corkerya44686c2022-11-23 18:16:51 +00003310 if (CalledByApi() && !options_->is_consent_deferred) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003311 status = CopyBugreportIfUserConsented(calling_uid);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003312 if (status != Dumpstate::RunStatus::OK &&
3313 status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3314 // Do an early return if there were errors. We make an exception for consent
3315 // timing out because it's possible the user got distracted. In this case the
3316 // bugreport is not shared but made available for manual retrieval.
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003317 MYLOGI("User denied consent. Returning\n");
Nandana Duttd2f5f082019-01-18 17:13:52 +00003318 return status;
3319 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003320 if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3321 MYLOGI(
3322 "Did not receive user consent yet."
3323 " Will not copy the bugreport artifacts to caller.\n");
Abhijeet Kaur57627412019-04-17 16:00:09 +01003324 const String16 incidentcompanion("incidentcompanion");
3325 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
3326 if (ics != nullptr) {
3327 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3328 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3329 consent_callback_.get());
3330 } else {
3331 MYLOGD("Unable to cancel user consent; incidentcompanion service unavailable\n");
3332 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003333 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003334 }
3335
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003336 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003337 if (options_->do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09003338 for (int i = 0; i < 3; i++) {
3339 Vibrate(75);
3340 usleep((75 + 50) * 1000);
3341 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003342 }
3343
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003344 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
3345 progress_->GetInitialMax());
3346 progress_->Save();
3347 MYLOGI("done (id %d)\n", id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003348
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003349 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08003350
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003351 if (control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07003352 MYLOGD("Closing control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003353 close(control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07003354 }
3355
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003356 tombstone_data_.clear();
3357 anr_data_.clear();
Woody Lin20767a92022-11-29 15:50:24 +08003358 shutdown_checkpoints_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01003359
Nandana Duttd2f5f082019-01-18 17:13:52 +00003360 return (consent_callback_ != nullptr &&
3361 consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
3362 ? USER_CONSENT_TIMED_OUT
3363 : RunStatus::OK;
3364}
3365
Paul Chang0d2aad72020-02-13 20:04:03 +08003366void Dumpstate::MaybeTakeEarlyScreenshot() {
3367 if (!options_->do_screenshot || !do_early_screenshot_) {
3368 return;
3369 }
3370
3371 TakeScreenshot();
3372}
3373
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003374void Dumpstate::MaybeSnapshotSystemTrace() {
3375 // If a background system trace is happening and is marked as "suitable for
3376 // bugreport" (i.e. bugreport_score > 0 in the trace config), this command
3377 // will stop it and serialize into SYSTEM_TRACE_SNAPSHOT. In the (likely)
3378 // case that no trace is ongoing, this command is a no-op.
3379 // Note: this should not be enqueued as we need to freeze the trace before
3380 // dumpstate starts. Otherwise the trace ring buffers will contain mostly
3381 // the dumpstate's own activity which is irrelevant.
3382 int res = RunCommand(
3383 "SERIALIZE PERFETTO TRACE",
3384 {"perfetto", "--save-for-bugreport"},
3385 CommandOptions::WithTimeout(10)
3386 .DropRoot()
3387 .CloseAllFileDescriptorsOnExec()
3388 .Build());
3389 has_system_trace_ = res == 0;
3390 // MaybeAddSystemTraceToZip() will take care of copying the trace in the zip
3391 // file in the later stages.
3392}
3393
Kean Mariotti306633e2022-09-05 16:30:47 +00003394void Dumpstate::MaybeSnapshotUiTraces() {
3395 if (PropertiesHelper::IsUserBuild() || options_->use_predumped_ui_data) {
3396 return;
3397 }
3398
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003399 const std::vector<std::vector<std::string>> dumpTracesForBugReportCommands = {
3400 {"dumpsys", "activity", "service", "SystemUIService", "WMShell", "protolog",
3401 "save-for-bugreport"},
3402 {"dumpsys", "activity", "service", "SystemUIService", "WMShell", "transitions", "tracing",
3403 "save-for-bugreport"},
3404 {"cmd", "input_method", "tracing", "save-for-bugreport"},
3405 {"cmd", "window", "tracing", "save-for-bugreport"},
3406 {"cmd", "window", "shell", "tracing", "save-for-bugreport"},
3407 };
Hongwei Wang39229132023-01-24 15:09:59 -08003408
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003409 for (const auto& command : dumpTracesForBugReportCommands) {
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003410 RunCommand(
3411 // Empty name because it's not intended to be classified as a bugreport section.
3412 // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003413 "", command,
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003414 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
3415 }
Kean Mariotti306633e2022-09-05 16:30:47 +00003416
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003417 // This command needs to be run as root
Kean Mariotti306633e2022-09-05 16:30:47 +00003418 static const auto SURFACEFLINGER_COMMAND_SAVE_ALL_TRACES = std::vector<std::string> {
3419 "service", "call", "SurfaceFlinger", "1042"
3420 };
3421 // Empty name because it's not intended to be classified as a bugreport section.
3422 // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
3423 RunCommand(
3424 "", SURFACEFLINGER_COMMAND_SAVE_ALL_TRACES,
3425 CommandOptions::WithTimeout(10).Always().AsRoot().RedirectStderr().Build());
3426}
3427
3428void Dumpstate::MaybePostProcessUiTraces() {
3429 if (PropertiesHelper::IsUserBuild()) {
3430 return;
3431 }
3432
3433 RunCommand(
3434 // Empty name because it's not intended to be classified as a bugreport section.
3435 // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
3436 "", {
3437 "/system/xbin/su", "system",
3438 "/system/bin/layertracegenerator",
3439 "/data/misc/wmtrace/transactions_trace.winscope",
3440 "/data/misc/wmtrace/layers_trace_from_transactions.winscope"
3441 },
3442 CommandOptions::WithTimeout(120).Always().RedirectStderr().Build());
3443}
3444
3445void Dumpstate::MaybeAddUiTracesToZip() {
3446 if (PropertiesHelper::IsUserBuild()) {
3447 return;
3448 }
3449
3450 ds.AddDir(WMTRACE_DATA_DIR, false);
Yohei Yukawa95305b32021-03-09 07:54:27 -08003451}
3452
Paul Changeb4b4642020-05-28 22:05:47 +08003453void Dumpstate::onUiIntensiveBugreportDumpsFinished(int32_t calling_uid) {
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003454 if (multiuser_get_app_id(calling_uid) == AID_SHELL || !CalledByApi()) {
Paul Changc490e662020-04-11 18:14:09 +08003455 return;
3456 }
3457 if (listener_ != nullptr) {
3458 // Let listener know ui intensive bugreport dumps are finished, then it can do event
3459 // handling if required.
Paul Changeb4b4642020-05-28 22:05:47 +08003460 listener_->onUiIntensiveBugreportDumpsFinished();
Paul Changc490e662020-04-11 18:14:09 +08003461 }
3462}
3463
Jichao Lie89d9c12019-11-21 19:02:51 -08003464void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) {
Gavin Corkerya44686c2022-11-23 18:16:51 +00003465 if (multiuser_get_app_id(calling_uid) == AID_SHELL ||
3466 !CalledByApi() || options_->is_consent_deferred) {
3467 // No need to get consent for shell triggered dumpstates, or not
3468 // through bugreporting API (i.e. no fd to copy back), or when consent
3469 // is deferred.
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003470 return;
3471 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003472 consent_callback_ = new ConsentCallback();
3473 const String16 incidentcompanion("incidentcompanion");
3474 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
Jichao Lie89d9c12019-11-21 19:02:51 -08003475 android::String16 package(calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003476 if (ics != nullptr) {
3477 MYLOGD("Checking user consent via incidentcompanion service\n");
Steven Leeb573eb82022-11-29 22:31:35 +08003478 int flags = 0x1; // IncidentManager.FLAG_CONFIRMATION_DIALOG
3479 if (IsConsentlessBugreportAllowed(*options_)) {
3480 flags |= 0x2; // IncidentManager.FLAG_ALLOW_CONSENTLESS_BUGREPORT
3481 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003482 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
Steven Leeb573eb82022-11-29 22:31:35 +08003483 calling_uid, package, String16(), String16(), flags, consent_callback_.get());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003484 } else {
3485 MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
3486 }
3487}
3488
Nandana Dutt5c390032019-03-12 10:52:56 +00003489bool Dumpstate::IsUserConsentDenied() const {
3490 return ds.consent_callback_ != nullptr &&
3491 ds.consent_callback_->getResult() == UserConsentResult::DENIED;
3492}
3493
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01003494bool Dumpstate::CalledByApi() const {
3495 return ds.options_->bugreport_fd.get() != -1 ? true : false;
3496}
3497
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003498void Dumpstate::CleanupTmpFiles() {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003499 android::os::UnlinkAndLogOnError(tmp_path_);
3500 android::os::UnlinkAndLogOnError(screenshot_path_);
3501 android::os::UnlinkAndLogOnError(path_);
Gavin Corkery789d7a52021-02-24 23:52:35 +00003502 if (dump_traces_path != nullptr) {
3503 android::os::UnlinkAndLogOnError(dump_traces_path);
3504 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003505}
3506
Rhed Jao5377d792020-07-16 17:37:39 +08003507void Dumpstate::EnableParallelRunIfNeeded() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003508 if (!PropertiesHelper::IsParallelRun()) {
Rhed Jao5377d792020-07-16 17:37:39 +08003509 return;
3510 }
3511 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003512 zip_entry_tasks_ = std::make_unique<TaskQueue>();
Rhed Jao5377d792020-07-16 17:37:39 +08003513}
3514
3515void Dumpstate::ShutdownDumpPool() {
3516 if (dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08003517 dump_pool_.reset();
Rhed Jao5377d792020-07-16 17:37:39 +08003518 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003519 if (zip_entry_tasks_) {
3520 zip_entry_tasks_->run(/* do_cancel = */true);
3521 zip_entry_tasks_ = nullptr;
3522 }
3523}
3524
3525void Dumpstate::EnqueueAddZipEntryAndCleanupIfNeeded(const std::string& entry_name,
3526 const std::string& entry_path) {
3527 auto func_add_zip_entry_and_cleanup = [=](bool task_cancelled) {
3528 if (!task_cancelled) {
3529 AddZipEntry(entry_name, entry_path);
3530 }
3531 android::os::UnlinkAndLogOnError(entry_path);
3532 };
3533 if (zip_entry_tasks_) {
3534 // Enqueues AddZipEntryAndCleanup function if the parallel run is enabled.
3535 zip_entry_tasks_->add(func_add_zip_entry_and_cleanup, _1);
3536 } else {
3537 // Invokes AddZipEntryAndCleanup immediately
3538 std::invoke(func_add_zip_entry_and_cleanup, /* task_cancelled = */false);
3539 }
Rhed Jao5377d792020-07-16 17:37:39 +08003540}
3541
Nandana Duttd2f5f082019-01-18 17:13:52 +00003542Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
3543 MYLOGD("User denied consent; deleting files and returning\n");
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003544 CleanupTmpFiles();
Nandana Duttd2f5f082019-01-18 17:13:52 +00003545 return USER_CONSENT_DENIED;
3546}
3547
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003548Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented(int32_t calling_uid) {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003549 // If the caller has asked to copy the bugreport over to their directory, we need explicit
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003550 // user consent (unless the caller is Shell).
3551 UserConsentResult consent_result;
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003552 if (multiuser_get_app_id(calling_uid) == AID_SHELL) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003553 consent_result = UserConsentResult::APPROVED;
3554 } else {
3555 consent_result = consent_callback_->getResult();
3556 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003557 if (consent_result == UserConsentResult::UNAVAILABLE) {
3558 // User has not responded yet.
3559 uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
Hunter Knepshield70610fa2020-01-03 15:27:33 -08003560 // Telephony is a fast report type, particularly on user builds where information may be
3561 // more aggressively limited. To give the user time to read the consent dialog, increase the
3562 // timeout.
3563 uint64_t timeout_ms = options_->telephony_only ? TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS
3564 : USER_CONSENT_TIMEOUT_MS;
3565 if (elapsed_ms < timeout_ms) {
3566 uint delay_seconds = (timeout_ms - elapsed_ms) / 1000;
Nandana Duttd2f5f082019-01-18 17:13:52 +00003567 MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
3568 sleep(delay_seconds);
3569 }
3570 consent_result = consent_callback_->getResult();
3571 }
3572 if (consent_result == UserConsentResult::DENIED) {
3573 // User has explicitly denied sharing with the app. To be safe delete the
3574 // internal bugreport & tmp files.
3575 return HandleUserConsentDenied();
3576 }
3577 if (consent_result == UserConsentResult::APPROVED) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00003578 bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
3579 if (copy_succeeded) {
3580 android::os::UnlinkAndLogOnError(path_);
Abhijeet Kaur9ce94672020-04-01 17:22:36 +01003581 if (options_->do_screenshot &&
3582 options_->screenshot_fd.get() != -1 &&
3583 !options_->is_screenshot_copied) {
3584 copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
3585 options_->screenshot_fd.get());
3586 options_->is_screenshot_copied = copy_succeeded;
3587 if (copy_succeeded) {
3588 android::os::UnlinkAndLogOnError(screenshot_path_);
3589 }
3590 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003591 }
3592 return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
3593 } else if (consent_result == UserConsentResult::UNAVAILABLE) {
3594 // consent_result is still UNAVAILABLE. The user has likely not responded yet.
3595 // Since we do not have user consent to share the bugreport it does not get
3596 // copied over to the calling app but remains in the internal directory from
3597 // where the user can manually pull it.
Paul Changce644212021-05-11 16:06:45 +08003598 std::string final_path = GetPath(".zip");
3599 bool copy_succeeded = android::os::CopyFileToFile(path_, final_path);
3600 if (copy_succeeded) {
3601 android::os::UnlinkAndLogOnError(path_);
3602 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003603 return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
3604 }
3605 // Unknown result; must be a programming error.
3606 MYLOGE("Unknown user consent result:%d\n", consent_result);
3607 return Dumpstate::RunStatus::ERROR;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003608}
3609
Nandana Duttf02564e2019-02-15 15:24:24 +00003610Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003611 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
3612 Dumpstate::RunStatus status = options->Initialize(argc, argv);
3613 if (status == Dumpstate::RunStatus::OK) {
Nandana Duttf02564e2019-02-15 15:24:24 +00003614 SetOptions(std::move(options));
Nandana Duttd2f5f082019-01-18 17:13:52 +00003615 // When directly running dumpstate binary, the output is not expected to be written
3616 // to any external file descriptor.
Nandana Duttf02564e2019-02-15 15:24:24 +00003617 assert(options_->bugreport_fd.get() == -1);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003618
3619 // calling_uid and calling_package are for user consent to share the bugreport with
Abhijeet Kaura407fb82020-03-27 12:51:12 +00003620 // an app; they are irrelevant here because bugreport is triggered via command line.
3621 // Update Last ID before calling Run().
3622 Initialize();
Nikhil Kumarb70622a2023-06-15 15:37:19 +01003623 status = Run(0 /* calling_uid */, "" /* calling_package */);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003624 }
Nandana Duttf02564e2019-02-15 15:24:24 +00003625 return status;
3626}
3627
3628/* Main entry point for dumpstate binary. */
3629int run_main(int argc, char* argv[]) {
3630 Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003631
3632 switch (status) {
3633 case Dumpstate::RunStatus::OK:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003634 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003635 case Dumpstate::RunStatus::HELP:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003636 ShowUsage();
3637 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003638 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003639 fprintf(stderr, "Invalid combination of args\n");
3640 ShowUsage();
3641 exit(1);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003642 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003643 FALLTHROUGH_INTENDED;
3644 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3645 FALLTHROUGH_INTENDED;
3646 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003647 exit(2);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003648 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003649}
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003650
3651// TODO(111441001): Default DumpOptions to sensible values.
3652Dumpstate::Dumpstate(const std::string& version)
3653 : pid_(getpid()),
3654 options_(new Dumpstate::DumpOptions()),
Nandana Dutt402a8392019-06-14 14:25:13 +01003655 last_reported_percent_progress_(0),
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003656 version_(version),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003657 now_(time(nullptr)),
3658 open_socket_fn_(open_socket) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003659}
3660
3661Dumpstate& Dumpstate::GetInstance() {
3662 static Dumpstate singleton_(android::base::GetProperty("dumpstate.version", VERSION_CURRENT));
3663 return singleton_;
3664}
3665
Rhed Jao5377d792020-07-16 17:37:39 +08003666DurationReporter::DurationReporter(const std::string& title, bool logcat_only, bool verbose,
3667 int duration_fd) : title_(title), logcat_only_(logcat_only), verbose_(verbose),
3668 duration_fd_(duration_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003669 if (!title_.empty()) {
3670 started_ = Nanotime();
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003671 if (title_.find("SHOW MAP") == std::string::npos) {
3672 ATRACE_ASYNC_BEGIN(title_.c_str(), 0);
3673 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003674 }
3675}
3676
3677DurationReporter::~DurationReporter() {
3678 if (!title_.empty()) {
3679 float elapsed = (float)(Nanotime() - started_) / NANOS_PER_SEC;
chenqiwuaf8b2d92019-12-12 18:53:51 +08003680 if (elapsed >= .5f || verbose_) {
3681 MYLOGD("Duration of '%s': %.2fs\n", title_.c_str(), elapsed);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003682 }
chenqiwuaf8b2d92019-12-12 18:53:51 +08003683 if (!logcat_only_) {
3684 // Use "Yoda grammar" to make it easier to grep|sort sections.
Rhed Jao5377d792020-07-16 17:37:39 +08003685 dprintf(duration_fd_, "------ %.3fs was the duration of '%s' ------\n",
3686 elapsed, title_.c_str());
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003687 }
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003688 if (title_.find("SHOW MAP") == std::string::npos) {
3689 ATRACE_ASYNC_END(title_.c_str(), 0);
3690 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003691 }
3692}
3693
3694const int32_t Progress::kDefaultMax = 5000;
3695
3696Progress::Progress(const std::string& path) : Progress(Progress::kDefaultMax, 1.1, path) {
3697}
3698
3699Progress::Progress(int32_t initial_max, int32_t progress, float growth_factor)
3700 : Progress(initial_max, growth_factor, "") {
3701 progress_ = progress;
3702}
3703
3704Progress::Progress(int32_t initial_max, float growth_factor, const std::string& path)
3705 : initial_max_(initial_max),
3706 progress_(0),
3707 max_(initial_max),
3708 growth_factor_(growth_factor),
3709 n_runs_(0),
3710 average_max_(0),
3711 path_(path) {
3712 if (!path_.empty()) {
3713 Load();
3714 }
3715}
3716
3717void Progress::Load() {
3718 MYLOGD("Loading stats from %s\n", path_.c_str());
3719 std::string content;
3720 if (!android::base::ReadFileToString(path_, &content)) {
3721 MYLOGI("Could not read stats from %s; using max of %d\n", path_.c_str(), max_);
3722 return;
3723 }
3724 if (content.empty()) {
3725 MYLOGE("No stats (empty file) on %s; using max of %d\n", path_.c_str(), max_);
3726 return;
3727 }
3728 std::vector<std::string> lines = android::base::Split(content, "\n");
3729
3730 if (lines.size() < 1) {
3731 MYLOGE("Invalid stats on file %s: not enough lines (%d). Using max of %d\n", path_.c_str(),
3732 (int)lines.size(), max_);
3733 return;
3734 }
3735 char* ptr;
3736 n_runs_ = strtol(lines[0].c_str(), &ptr, 10);
3737 average_max_ = strtol(ptr, nullptr, 10);
3738 if (n_runs_ <= 0 || average_max_ <= 0 || n_runs_ > STATS_MAX_N_RUNS ||
3739 average_max_ > STATS_MAX_AVERAGE) {
3740 MYLOGE("Invalid stats line on file %s: %s\n", path_.c_str(), lines[0].c_str());
3741 initial_max_ = Progress::kDefaultMax;
3742 } else {
3743 initial_max_ = average_max_;
3744 }
3745 max_ = initial_max_;
3746
3747 MYLOGI("Average max progress: %d in %d runs; estimated max: %d\n", average_max_, n_runs_, max_);
3748}
3749
3750void Progress::Save() {
3751 int32_t total = n_runs_ * average_max_ + progress_;
3752 int32_t runs = n_runs_ + 1;
3753 int32_t average = floor(((float)total) / runs);
3754 MYLOGI("Saving stats (total=%d, runs=%d, average=%d) on %s\n", total, runs, average,
3755 path_.c_str());
3756 if (path_.empty()) {
3757 return;
3758 }
3759
3760 std::string content = android::base::StringPrintf("%d %d\n", runs, average);
3761 if (!android::base::WriteStringToFile(content, path_)) {
3762 MYLOGE("Could not save stats on %s\n", path_.c_str());
3763 }
3764}
3765
3766int32_t Progress::Get() const {
3767 return progress_;
3768}
3769
3770bool Progress::Inc(int32_t delta_sec) {
3771 bool changed = false;
3772 if (delta_sec >= 0) {
3773 progress_ += delta_sec;
3774 if (progress_ > max_) {
3775 int32_t old_max = max_;
3776 max_ = floor((float)progress_ * growth_factor_);
3777 MYLOGD("Adjusting max progress from %d to %d\n", old_max, max_);
3778 changed = true;
3779 }
3780 }
3781 return changed;
3782}
3783
3784int32_t Progress::GetMax() const {
3785 return max_;
3786}
3787
3788int32_t Progress::GetInitialMax() const {
3789 return initial_max_;
3790}
3791
3792void Progress::Dump(int fd, const std::string& prefix) const {
3793 const char* pr = prefix.c_str();
3794 dprintf(fd, "%sprogress: %d\n", pr, progress_);
3795 dprintf(fd, "%smax: %d\n", pr, max_);
3796 dprintf(fd, "%sinitial_max: %d\n", pr, initial_max_);
3797 dprintf(fd, "%sgrowth_factor: %0.2f\n", pr, growth_factor_);
3798 dprintf(fd, "%spath: %s\n", pr, path_.c_str());
3799 dprintf(fd, "%sn_runs: %d\n", pr, n_runs_);
3800 dprintf(fd, "%saverage_max: %d\n", pr, average_max_);
3801}
3802
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003803std::string Dumpstate::GetPath(const std::string& suffix) const {
3804 return GetPath(bugreport_internal_dir_, suffix);
3805}
3806
3807std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
3808 return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
3809 name_.c_str(), suffix.c_str());
3810}
3811
3812void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
3813 progress_ = std::move(progress);
3814}
3815
3816void for_each_userid(void (*func)(int), const char *header) {
3817 std::string title = header == nullptr ? "for_each_userid" : android::base::StringPrintf(
3818 "for_each_userid(%s)", header);
3819 DurationReporter duration_reporter(title);
3820 if (PropertiesHelper::IsDryRun()) return;
3821
3822 DIR *d;
3823 struct dirent *de;
3824
3825 if (header) printf("\n------ %s ------\n", header);
3826 func(0);
3827
3828 if (!(d = opendir("/data/system/users"))) {
3829 printf("Failed to open /data/system/users (%s)\n", strerror(errno));
3830 return;
3831 }
3832
3833 while ((de = readdir(d))) {
3834 int userid;
3835 if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
3836 continue;
3837 }
3838 func(userid);
3839 }
3840
3841 closedir(d);
3842}
3843
3844static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
3845 DIR *d;
3846 struct dirent *de;
3847
3848 if (!(d = opendir("/proc"))) {
3849 printf("Failed to open /proc (%s)\n", strerror(errno));
3850 return;
3851 }
3852
3853 if (header) printf("\n------ %s ------\n", header);
3854 while ((de = readdir(d))) {
3855 if (ds.IsUserConsentDenied()) {
3856 MYLOGE(
3857 "Returning early because user denied consent to share bugreport with calling app.");
3858 closedir(d);
3859 return;
3860 }
3861 int pid;
3862 int fd;
3863 char cmdpath[255];
3864 char cmdline[255];
3865
3866 if (!(pid = atoi(de->d_name))) {
3867 continue;
3868 }
3869
3870 memset(cmdline, 0, sizeof(cmdline));
3871
3872 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
3873 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3874 TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
3875 close(fd);
3876 if (cmdline[0]) {
3877 helper(pid, cmdline, arg);
3878 continue;
3879 }
3880 }
3881
3882 // if no cmdline, a kernel thread has comm
3883 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
3884 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3885 TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
3886 close(fd);
3887 if (cmdline[1]) {
3888 cmdline[0] = '[';
3889 size_t len = strcspn(cmdline, "\f\b\r\n");
3890 cmdline[len] = ']';
3891 cmdline[len+1] = '\0';
3892 }
3893 }
3894 if (!cmdline[0]) {
3895 strcpy(cmdline, "N/A");
3896 }
3897 helper(pid, cmdline, arg);
3898 }
3899
3900 closedir(d);
3901}
3902
3903static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
3904 for_each_pid_func *func = (for_each_pid_func*) arg;
3905 func(pid, cmdline);
3906}
3907
3908void for_each_pid(for_each_pid_func func, const char *header) {
3909 std::string title = header == nullptr ? "for_each_pid"
3910 : android::base::StringPrintf("for_each_pid(%s)", header);
3911 DurationReporter duration_reporter(title);
3912 if (PropertiesHelper::IsDryRun()) return;
3913
3914 __for_each_pid(for_each_pid_helper, header, (void *) func);
3915}
3916
3917static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
3918 DIR *d;
3919 struct dirent *de;
3920 char taskpath[255];
3921 for_each_tid_func *func = (for_each_tid_func *) arg;
3922
3923 snprintf(taskpath, sizeof(taskpath), "/proc/%d/task", pid);
3924
3925 if (!(d = opendir(taskpath))) {
3926 printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
3927 return;
3928 }
3929
3930 func(pid, pid, cmdline);
3931
3932 while ((de = readdir(d))) {
3933 if (ds.IsUserConsentDenied()) {
3934 MYLOGE(
3935 "Returning early because user denied consent to share bugreport with calling app.");
3936 closedir(d);
3937 return;
3938 }
3939 int tid;
3940 int fd;
3941 char commpath[255];
3942 char comm[255];
3943
3944 if (!(tid = atoi(de->d_name))) {
3945 continue;
3946 }
3947
3948 if (tid == pid)
3949 continue;
3950
3951 snprintf(commpath, sizeof(commpath), "/proc/%d/comm", tid);
3952 memset(comm, 0, sizeof(comm));
3953 if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
3954 strcpy(comm, "N/A");
3955 } else {
3956 char *c;
3957 TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
3958 close(fd);
3959
3960 c = strrchr(comm, '\n');
3961 if (c) {
3962 *c = '\0';
3963 }
3964 }
3965 func(pid, tid, comm);
3966 }
3967
3968 closedir(d);
3969}
3970
3971void for_each_tid(for_each_tid_func func, const char *header) {
3972 std::string title = header == nullptr ? "for_each_tid"
3973 : android::base::StringPrintf("for_each_tid(%s)", header);
3974 DurationReporter duration_reporter(title);
3975
3976 if (PropertiesHelper::IsDryRun()) return;
3977
3978 __for_each_pid(for_each_tid_helper, header, (void *) func);
3979}
3980
3981void show_wchan(int pid, int tid, const char *name) {
3982 if (PropertiesHelper::IsDryRun()) return;
3983
3984 char path[255];
3985 char buffer[255];
3986 int fd, ret, save_errno;
3987 char name_buffer[255];
3988
3989 memset(buffer, 0, sizeof(buffer));
3990
3991 snprintf(path, sizeof(path), "/proc/%d/wchan", tid);
3992 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
3993 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
3994 return;
3995 }
3996
3997 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3998 save_errno = errno;
3999 close(fd);
4000
4001 if (ret < 0) {
4002 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
4003 return;
4004 }
4005
4006 snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
4007 pid == tid ? 0 : 3, "", name);
4008
4009 printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
4010
4011 return;
4012}
4013
4014// print time in centiseconds
4015static void snprcent(char *buffer, size_t len, size_t spc,
4016 unsigned long long time) {
4017 static long hz; // cache discovered hz
4018
4019 if (hz <= 0) {
4020 hz = sysconf(_SC_CLK_TCK);
4021 if (hz <= 0) {
4022 hz = 1000;
4023 }
4024 }
4025
4026 // convert to centiseconds
4027 time = (time * 100 + (hz / 2)) / hz;
4028
4029 char str[16];
4030
4031 snprintf(str, sizeof(str), " %llu.%02u",
4032 time / 100, (unsigned)(time % 100));
4033 size_t offset = strlen(buffer);
4034 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
4035 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
4036}
4037
4038// print permille as a percent
4039static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
4040 char str[16];
4041
4042 snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
4043 size_t offset = strlen(buffer);
4044 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
4045 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
4046}
4047
4048void show_showtime(int pid, const char *name) {
4049 if (PropertiesHelper::IsDryRun()) return;
4050
4051 char path[255];
4052 char buffer[1023];
4053 int fd, ret, save_errno;
4054
4055 memset(buffer, 0, sizeof(buffer));
4056
4057 snprintf(path, sizeof(path), "/proc/%d/stat", pid);
4058 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
4059 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
4060 return;
4061 }
4062
4063 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
4064 save_errno = errno;
4065 close(fd);
4066
4067 if (ret < 0) {
4068 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
4069 return;
4070 }
4071
4072 // field 14 is utime
4073 // field 15 is stime
4074 // field 42 is iotime
4075 unsigned long long utime = 0, stime = 0, iotime = 0;
4076 if (sscanf(buffer,
4077 "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
4078 "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
4079 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
4080 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
4081 &utime, &stime, &iotime) != 3) {
4082 return;
4083 }
4084
4085 unsigned long long total = utime + stime;
4086 if (!total) {
4087 return;
4088 }
4089
4090 unsigned permille = (iotime * 1000 + (total / 2)) / total;
4091 if (permille > 1000) {
4092 permille = 1000;
4093 }
4094
4095 // try to beautify and stabilize columns at <80 characters
4096 snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
4097 if ((name[0] != '[') || utime) {
4098 snprcent(buffer, sizeof(buffer), 57, utime);
4099 }
4100 snprcent(buffer, sizeof(buffer), 65, stime);
4101 if ((name[0] != '[') || iotime) {
4102 snprcent(buffer, sizeof(buffer), 73, iotime);
4103 }
4104 if (iotime) {
4105 snprdec(buffer, sizeof(buffer), 79, permille);
4106 }
4107 puts(buffer); // adds a trailing newline
4108
4109 return;
4110}
4111
4112void do_dmesg() {
4113 const char *title = "KERNEL LOG (dmesg)";
4114 DurationReporter duration_reporter(title);
4115 printf("------ %s ------\n", title);
4116
4117 if (PropertiesHelper::IsDryRun()) return;
4118
4119 /* Get size of kernel buffer */
4120 int size = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
4121 if (size <= 0) {
4122 printf("Unexpected klogctl return value: %d\n\n", size);
4123 return;
4124 }
4125 char *buf = (char *) malloc(size + 1);
4126 if (buf == nullptr) {
4127 printf("memory allocation failed\n\n");
4128 return;
4129 }
4130 int retval = klogctl(KLOG_READ_ALL, buf, size);
4131 if (retval < 0) {
4132 printf("klogctl failure\n\n");
4133 free(buf);
4134 return;
4135 }
4136 buf[retval] = '\0';
4137 printf("%s\n\n", buf);
4138 free(buf);
4139 return;
4140}
4141
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004142int Dumpstate::DumpFile(const std::string& title, const std::string& path) {
4143 DurationReporter duration_reporter(title);
4144
4145 int status = DumpFileToFd(STDOUT_FILENO, title, path);
4146
4147 UpdateProgress(WEIGHT_FILE);
4148
4149 return status;
4150}
4151
4152int read_file_as_long(const char *path, long int *output) {
4153 int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
4154 if (fd < 0) {
4155 int err = errno;
4156 MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
4157 return -1;
4158 }
4159 char buffer[50];
4160 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
4161 if (bytes_read == -1) {
4162 MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
4163 return -2;
4164 }
4165 if (bytes_read == 0) {
4166 MYLOGE("File %s is empty\n", path);
4167 return -3;
4168 }
4169 *output = atoi(buffer);
4170 return 0;
4171}
4172
4173/* calls skip to gate calling dump_from_fd recursively
4174 * in the specified directory. dump_from_fd defaults to
4175 * dump_file_from_fd above when set to NULL. skip defaults
4176 * to false when set to NULL. dump_from_fd will always be
4177 * called with title NULL.
4178 */
4179int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
4180 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4181 DurationReporter duration_reporter(title);
4182 DIR *dirp;
4183 struct dirent *d;
4184 char *newpath = nullptr;
4185 const char *slash = "/";
4186 int retval = 0;
4187
4188 if (!title.empty()) {
4189 printf("------ %s (%s) ------\n", title.c_str(), dir);
4190 }
4191 if (PropertiesHelper::IsDryRun()) return 0;
4192
4193 if (dir[strlen(dir) - 1] == '/') {
4194 ++slash;
4195 }
4196 dirp = opendir(dir);
4197 if (dirp == nullptr) {
4198 retval = -errno;
4199 MYLOGE("%s: %s\n", dir, strerror(errno));
4200 return retval;
4201 }
4202
4203 if (!dump_from_fd) {
4204 dump_from_fd = dump_file_from_fd;
4205 }
4206 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4207 if ((d->d_name[0] == '.')
4208 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4209 || (d->d_name[1] == '\0'))) {
4210 continue;
4211 }
4212 asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
4213 (d->d_type == DT_DIR) ? "/" : "");
4214 if (!newpath) {
4215 retval = -errno;
4216 continue;
4217 }
4218 if (skip && (*skip)(newpath)) {
4219 continue;
4220 }
4221 if (d->d_type == DT_DIR) {
4222 int ret = dump_files("", newpath, skip, dump_from_fd);
4223 if (ret < 0) {
4224 retval = ret;
4225 }
4226 continue;
4227 }
4228 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
4229 if (fd.get() < 0) {
4230 retval = -1;
4231 printf("*** %s: %s\n", newpath, strerror(errno));
4232 continue;
4233 }
4234 (*dump_from_fd)(nullptr, newpath, fd.get());
4235 }
4236 closedir(dirp);
4237 if (!title.empty()) {
4238 printf("\n");
4239 }
4240 return retval;
4241}
4242
4243/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
4244 * it's possible to avoid issues where opening the file itself can get
4245 * stuck.
4246 */
4247int dump_file_from_fd(const char *title, const char *path, int fd) {
4248 if (PropertiesHelper::IsDryRun()) return 0;
4249
4250 int flags = fcntl(fd, F_GETFL);
4251 if (flags == -1) {
4252 printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
4253 return -1;
4254 } else if (!(flags & O_NONBLOCK)) {
4255 printf("*** %s: fd must have O_NONBLOCK set.\n", path);
4256 return -1;
4257 }
4258 return DumpFileFromFdToFd(title, path, fd, STDOUT_FILENO, PropertiesHelper::IsDryRun());
4259}
4260
4261int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004262 const CommandOptions& options, bool verbose_duration, int out_fd) {
4263 DurationReporter duration_reporter(title, false /* logcat_only */,
4264 verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004265
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004266 int status = RunCommandToFd(out_fd, title, full_command, options);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004267
4268 /* TODO: for now we're simplifying the progress calculation by using the
4269 * timeout as the weight. It's a good approximation for most cases, except when calling dumpsys,
4270 * where its weight should be much higher proportionally to its timeout.
4271 * Ideally, it should use a options.EstimatedDuration() instead...*/
4272 UpdateProgress(options.Timeout());
4273
4274 return status;
4275}
4276
4277void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
Rhed Jaoe017f982020-07-21 17:58:41 +08004278 const CommandOptions& options, long dumpsysTimeoutMs, int out_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004279 long timeout_ms = dumpsysTimeoutMs > 0 ? dumpsysTimeoutMs : options.TimeoutInMs();
4280 std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-T", std::to_string(timeout_ms)};
4281 dumpsys.insert(dumpsys.end(), dumpsys_args.begin(), dumpsys_args.end());
Rhed Jaoe017f982020-07-21 17:58:41 +08004282 RunCommand(title, dumpsys, options, false, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004283}
4284
Dieter Hsu105ad0c2020-09-29 15:23:33 +08004285static int open_socket(const char* service) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004286 int s = android_get_control_socket(service);
4287 if (s < 0) {
4288 MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
4289 return -1;
4290 }
4291 fcntl(s, F_SETFD, FD_CLOEXEC);
4292
4293 // Set backlog to 0 to make sure that queue size will be minimum.
4294 // In Linux, because the minimum queue will be 1, connect() will be blocked
4295 // if the other clients already called connect() and the connection request was not accepted.
4296 if (listen(s, 0) < 0) {
4297 MYLOGE("listen(control socket): %s\n", strerror(errno));
4298 return -1;
4299 }
4300
4301 struct sockaddr addr;
4302 socklen_t alen = sizeof(addr);
Abhijeet Kaur2113cae2019-09-13 09:24:15 +01004303 int fd = accept4(s, &addr, &alen, SOCK_CLOEXEC);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004304
4305 // Close socket just after accept(), to make sure that connect() by client will get error
4306 // when the socket is used by the other services.
4307 // There is still a race condition possibility between accept and close, but there is no way
4308 // to close-on-accept atomically.
4309 // See detail; b/123306389#comment25
4310 close(s);
4311
4312 if (fd < 0) {
4313 MYLOGE("accept(control socket): %s\n", strerror(errno));
4314 return -1;
4315 }
4316
4317 return fd;
4318}
4319
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004320// TODO: should call is_valid_output_file and/or be merged into it.
4321void create_parent_dirs(const char *path) {
4322 char *chp = const_cast<char *> (path);
4323
4324 /* skip initial slash */
4325 if (chp[0] == '/')
4326 chp++;
4327
4328 /* create leading directories, if necessary */
4329 struct stat dir_stat;
4330 while (chp && chp[0]) {
4331 chp = strchr(chp, '/');
4332 if (chp) {
4333 *chp = 0;
4334 if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
4335 MYLOGI("Creating directory %s\n", path);
4336 if (mkdir(path, 0770)) { /* drwxrwx--- */
4337 MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
4338 } else if (chown(path, AID_SHELL, AID_SHELL)) {
4339 MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
4340 }
4341 }
4342 *chp++ = '/';
4343 }
4344 }
4345}
4346
4347bool _redirect_to_file(FILE* redirect, char* path, int truncate_flag) {
4348 create_parent_dirs(path);
4349
4350 int fd = TEMP_FAILURE_RETRY(open(path,
4351 O_WRONLY | O_CREAT | truncate_flag | O_CLOEXEC | O_NOFOLLOW,
4352 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
4353 if (fd < 0) {
4354 MYLOGE("%s: %s\n", path, strerror(errno));
4355 return false;
4356 }
4357
4358 TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
4359 close(fd);
4360 return true;
4361}
4362
4363bool redirect_to_file(FILE* redirect, char* path) {
4364 return _redirect_to_file(redirect, path, O_TRUNC);
4365}
4366
4367bool redirect_to_existing_file(FILE* redirect, char* path) {
4368 return _redirect_to_file(redirect, path, O_APPEND);
4369}
4370
4371void dump_route_tables() {
4372 DurationReporter duration_reporter("DUMP ROUTE TABLES");
4373 if (PropertiesHelper::IsDryRun()) return;
4374 const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
4375 ds.DumpFile("RT_TABLES", RT_TABLES_PATH);
4376 FILE* fp = fopen(RT_TABLES_PATH, "re");
4377 if (!fp) {
4378 printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
4379 return;
4380 }
4381 char table[16];
4382 // Each line has an integer (the table number), a space, and a string (the table name). We only
4383 // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
4384 // Add a fixed max limit so this doesn't go awry.
4385 for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
4386 RunCommand("ROUTE TABLE IPv4", {"ip", "-4", "route", "show", "table", table});
4387 RunCommand("ROUTE TABLE IPv6", {"ip", "-6", "route", "show", "table", table});
4388 }
4389 fclose(fp);
4390}
4391
Li Li830179f2022-01-04 12:53:29 -08004392void dump_frozen_cgroupfs(const char *dir, int level,
4393 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4394 DIR *dirp;
4395 struct dirent *d;
4396 char *newpath = nullptr;
4397
4398 dirp = opendir(dir);
4399 if (dirp == nullptr) {
4400 MYLOGE("%s: %s\n", dir, strerror(errno));
4401 return;
4402 }
4403
4404 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4405 if ((d->d_name[0] == '.')
4406 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4407 || (d->d_name[1] == '\0'))) {
4408 continue;
4409 }
4410 if (d->d_type == DT_DIR) {
4411 asprintf(&newpath, "%s/%s/", dir, d->d_name);
4412 if (!newpath) {
4413 continue;
4414 }
4415 if (level == 0 && !strncmp(d->d_name, "uid_", 4)) {
4416 dump_frozen_cgroupfs(newpath, 1, dump_from_fd);
4417 } else if (level == 1 && !strncmp(d->d_name, "pid_", 4)) {
4418 char *freezer = nullptr;
4419 asprintf(&freezer, "%s/%s", newpath, "cgroup.freeze");
4420 if (freezer) {
4421 FILE* fp = fopen(freezer, "r");
4422 if (fp != NULL) {
4423 int frozen;
4424 fscanf(fp, "%d", &frozen);
4425 if (frozen > 0) {
4426 dump_files("", newpath, skip_none, dump_from_fd);
4427 }
4428 fclose(fp);
4429 }
4430 free(freezer);
4431 }
4432 }
4433 }
4434 }
4435 closedir(dirp);
4436}
4437
4438void dump_frozen_cgroupfs() {
Li Li830179f2022-01-04 12:53:29 -08004439 MYLOGD("Adding frozen processes from %s\n", CGROUPFS_DIR);
4440 DurationReporter duration_reporter("FROZEN CGROUPFS");
4441 if (PropertiesHelper::IsDryRun()) return;
4442 dump_frozen_cgroupfs(CGROUPFS_DIR, 0, _add_file_from_fd);
4443}
4444
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004445void Dumpstate::UpdateProgress(int32_t delta_sec) {
4446 if (progress_ == nullptr) {
4447 MYLOGE("UpdateProgress: progress_ not set\n");
4448 return;
4449 }
Rhed Jaobf63d8a2020-07-21 15:42:55 +08004450 // This function updates progress related members of the dumpstate and reports
4451 // progress percentage to the bugreport client. Since it could be called by
4452 // different dump tasks at the same time if the parallel run is enabled, a
4453 // mutex lock is necessary here to synchronize the call.
4454 std::lock_guard<std::recursive_mutex> lock(mutex_);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004455
4456 // Always update progess so stats can be tuned...
Nandana Dutt402a8392019-06-14 14:25:13 +01004457 progress_->Inc(delta_sec);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004458
4459 // ...but only notifiy listeners when necessary.
4460 if (!options_->do_progress_updates) return;
4461
4462 int progress = progress_->Get();
4463 int max = progress_->GetMax();
Nandana Dutt402a8392019-06-14 14:25:13 +01004464 int percent = 100 * progress / max;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004465
Nandana Dutt402a8392019-06-14 14:25:13 +01004466 if (last_reported_percent_progress_ > 0 && percent <= last_reported_percent_progress_) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004467 return;
4468 }
Nandana Dutt402a8392019-06-14 14:25:13 +01004469 last_reported_percent_progress_ = percent;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004470
4471 if (control_socket_fd_ >= 0) {
4472 dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
4473 fsync(control_socket_fd_);
4474 }
4475
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004476 if (listener_ != nullptr) {
Nandana Dutt235c6672019-11-14 15:22:32 +00004477 if (percent % 10 == 0) {
4478 // We don't want to spam logcat, so only log multiples of 10.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004479 MYLOGD("Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004480 } else {
4481 // stderr is ignored on normal invocations, but useful when calling
4482 // /system/bin/dumpstate directly for debuggging.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004483 fprintf(stderr, "Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004484 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004485
4486 listener_->onProgress(percent);
4487 }
4488}
4489
4490void Dumpstate::TakeScreenshot(const std::string& path) {
4491 const std::string& real_path = path.empty() ? screenshot_path_ : path;
4492 int status =
4493 RunCommand("", {"/system/bin/screencap", "-p", real_path},
4494 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
4495 if (status == 0) {
4496 MYLOGD("Screenshot saved on %s\n", real_path.c_str());
4497 } else {
4498 MYLOGE("Failed to take screenshot on %s\n", real_path.c_str());
4499 }
Paul Chang0d2aad72020-02-13 20:04:03 +08004500 if (listener_ != nullptr) {
4501 // Show a visual indication to indicate screenshot is taken via
4502 // IDumpstateListener.onScreenshotTaken()
4503 listener_->onScreenshotTaken(status == 0);
4504 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004505}
4506
4507bool is_dir(const char* pathname) {
4508 struct stat info;
4509 if (stat(pathname, &info) == -1) {
4510 return false;
4511 }
4512 return S_ISDIR(info.st_mode);
4513}
4514
4515time_t get_mtime(int fd, time_t default_mtime) {
4516 struct stat info;
4517 if (fstat(fd, &info) == -1) {
4518 return default_mtime;
4519 }
4520 return info.st_mtime;
4521}