blob: 2965a5933f8a9f5302062c26e4b91023b07e7497 [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 Huanga99452a2022-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 Huanga99452a2022-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 Huanga99452a2022-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. */
Ray Chencbf278a2023-11-20 07:49:45 +00001239 RunCommand("NETWORK INTERFACES", {"ip", "-s", "link"});
Jayachandran Ca94c7172017-06-10 15:08:12 -07001240 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 Huanga99452a2022-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 Huanga99452a2022-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 Huanga99452a2022-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 Menke9bf3b2b2023-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
Nandana Duttcf419a72019-03-14 10:40:17 +00002174Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
Gavin Corkery789d7a52021-02-24 23:52:35 +00002175 const std::string temp_file_pattern = ds.bugreport_internal_dir_ + "/dumptrace_XXXXXX";
Nandana Duttfaafd522019-03-11 09:23:09 +00002176 const size_t buf_size = temp_file_pattern.length() + 1;
2177 std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
2178 memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
2179
2180 // Create a new, empty file to receive all trace dumps.
2181 //
2182 // TODO: This can be simplified once we remove support for the old style
2183 // dumps. We can have a file descriptor passed in to dump_traces instead
2184 // of creating a file, closing it and then reopening it again.
2185 android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
2186 if (fd < 0) {
2187 MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002188 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002189 }
2190
2191 // Nobody should have access to this temporary file except dumpstate, but we
2192 // temporarily grant 'read' to 'others' here because this file is created
2193 // when tombstoned is still running as root, but dumped after dropping. This
2194 // can go away once support for old style dumping has.
2195 const int chmod_ret = fchmod(fd, 0666);
2196 if (chmod_ret < 0) {
2197 MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002198 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002199 }
2200
2201 std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
2202 if (proc.get() == nullptr) {
2203 MYLOGE("opendir /proc failed: %s\n", strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002204 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002205 }
2206
2207 // Number of times process dumping has timed out. If we encounter too many
2208 // failures, we'll give up.
2209 int timeout_failures = 0;
2210 bool dalvik_found = false;
2211
Jayant Chowdharya0a8eb22022-05-20 03:30:09 +00002212 const std::set<int> hal_pids = get_interesting_pids();
Nandana Duttfaafd522019-03-11 09:23:09 +00002213
2214 struct dirent* d;
2215 while ((d = readdir(proc.get()))) {
Nandana Duttcf419a72019-03-14 10:40:17 +00002216 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttfaafd522019-03-11 09:23:09 +00002217 int pid = atoi(d->d_name);
2218 if (pid <= 0) {
2219 continue;
2220 }
2221
Kevin Jeond0f8a982023-04-07 14:27:11 -04002222 // Skip cached processes.
2223 if (IsCached(pid)) {
2224 // For consistency, the header and footer to this message match those
2225 // dumped by debuggerd in the success case.
2226 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
2227 dprintf(fd, "Dump skipped for cached process.\n");
2228 dprintf(fd, "---- end %d ----", pid);
2229 continue;
2230 }
2231
Nandana Duttfaafd522019-03-11 09:23:09 +00002232 const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
2233 std::string exe;
2234 if (!android::base::Readlink(link_name, &exe)) {
2235 continue;
2236 }
2237
2238 bool is_java_process;
2239 if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
2240 // Don't bother dumping backtraces for the zygote.
2241 if (IsZygote(pid)) {
2242 continue;
2243 }
2244
2245 dalvik_found = true;
2246 is_java_process = true;
2247 } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
2248 is_java_process = false;
2249 } else {
2250 // Probably a native process we don't care about, continue.
2251 continue;
2252 }
2253
2254 // If 3 backtrace dumps fail in a row, consider debuggerd dead.
2255 if (timeout_failures == 3) {
2256 dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
2257 break;
2258 }
2259
2260 const uint64_t start = Nanotime();
2261 const int ret = dump_backtrace_to_file_timeout(
Kevin Jeonb8a39362023-04-04 15:00:34 -04002262 pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace, 3, fd);
Nandana Duttfaafd522019-03-11 09:23:09 +00002263
2264 if (ret == -1) {
2265 // For consistency, the header and footer to this message match those
2266 // dumped by debuggerd in the success case.
2267 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
2268 dprintf(fd, "Dump failed, likely due to a timeout.\n");
2269 dprintf(fd, "---- end %d ----", pid);
2270 timeout_failures++;
2271 continue;
2272 }
2273
2274 // We've successfully dumped stack traces, reset the failure count
2275 // and write a summary of the elapsed time to the file and continue with the
2276 // next process.
2277 timeout_failures = 0;
2278
2279 dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
2280 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
2281 }
2282
2283 if (!dalvik_found) {
2284 MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
2285 }
2286
Nandana Duttcf419a72019-03-14 10:40:17 +00002287 *path = file_name_buf.release();
2288 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002289}
2290
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002291static dumpstate_hal_hidl::DumpstateMode GetDumpstateHalModeHidl(
2292 const Dumpstate::BugreportMode bugreport_mode) {
2293 switch (bugreport_mode) {
2294 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2295 return dumpstate_hal_hidl::DumpstateMode::FULL;
2296 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2297 return dumpstate_hal_hidl::DumpstateMode::INTERACTIVE;
2298 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2299 return dumpstate_hal_hidl::DumpstateMode::REMOTE;
2300 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2301 return dumpstate_hal_hidl::DumpstateMode::WEAR;
2302 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2303 return dumpstate_hal_hidl::DumpstateMode::CONNECTIVITY;
2304 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2305 return dumpstate_hal_hidl::DumpstateMode::WIFI;
2306 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2307 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2308 }
2309 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2310}
2311
2312static dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode GetDumpstateHalModeAidl(
2313 const Dumpstate::BugreportMode bugreport_mode) {
2314 switch (bugreport_mode) {
2315 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2316 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::FULL;
2317 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2318 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::INTERACTIVE;
2319 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2320 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::REMOTE;
2321 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2322 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WEAR;
2323 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2324 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::CONNECTIVITY;
2325 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2326 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WIFI;
2327 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2328 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2329 }
2330 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2331}
2332
2333static void DoDumpstateBoardHidl(
2334 const sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_1_0,
2335 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2336 const Dumpstate::BugreportMode bugreport_mode,
2337 const size_t timeout_sec) {
2338
2339 using ScopedNativeHandle =
2340 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
2341 ScopedNativeHandle handle(native_handle_create(static_cast<int>(dumpstate_fds.size()), 0),
2342 [](native_handle_t* handle) {
2343 // we don't close file handle's here
2344 // via native_handle_close(handle)
2345 // instead we let dumpstate_fds close the file handles when
2346 // dumpstate_fds gets destroyed
2347 native_handle_delete(handle);
2348 });
2349 if (handle == nullptr) {
2350 MYLOGE("Could not create native_handle for dumpstate HAL\n");
2351 return;
2352 }
2353
2354 for (size_t i = 0; i < dumpstate_fds.size(); i++) {
2355 handle.get()->data[i] = dumpstate_fds[i].get();
2356 }
2357
2358 // Prefer version 1.1 if available. New devices launching with R are no longer allowed to
2359 // implement just 1.0.
2360 const char* descriptor_to_kill;
2361 using DumpstateBoardTask = std::packaged_task<bool()>;
2362 DumpstateBoardTask dumpstate_board_task;
2363 sp<dumpstate_hal_hidl::IDumpstateDevice> dumpstate_hal(
2364 dumpstate_hal_hidl::IDumpstateDevice::castFrom(dumpstate_hal_1_0));
2365 if (dumpstate_hal != nullptr) {
2366 MYLOGI("Using IDumpstateDevice v1.1 HIDL HAL");
2367
2368 dumpstate_hal_hidl::DumpstateMode dumpstate_hal_mode =
2369 GetDumpstateHalModeHidl(bugreport_mode);
2370
2371 descriptor_to_kill = dumpstate_hal_hidl::IDumpstateDevice::descriptor;
2372 dumpstate_board_task =
2373 DumpstateBoardTask([timeout_sec, dumpstate_hal_mode, dumpstate_hal, &handle]() -> bool {
2374 ::android::hardware::Return<dumpstate_hal_hidl::DumpstateStatus> status =
2375 dumpstate_hal->dumpstateBoard_1_1(handle.get(), dumpstate_hal_mode,
2376 SEC_TO_MSEC(timeout_sec));
2377 if (!status.isOk()) {
2378 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2379 return false;
2380 } else if (status != dumpstate_hal_hidl::DumpstateStatus::OK) {
2381 MYLOGE("dumpstateBoard failed with DumpstateStatus::%s\n",
2382 dumpstate_hal_hidl::toString(status).c_str());
2383 return false;
2384 }
2385 return true;
2386 });
2387 } else {
2388 MYLOGI("Using IDumpstateDevice v1.0 HIDL HAL");
2389
2390 descriptor_to_kill = dumpstate_hal_hidl_1_0::IDumpstateDevice::descriptor;
2391 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal_1_0, &handle]() -> bool {
2392 ::android::hardware::Return<void> status =
2393 dumpstate_hal_1_0->dumpstateBoard(handle.get());
2394 if (!status.isOk()) {
2395 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2396 return false;
2397 }
2398 return true;
2399 });
2400 }
2401 auto result = dumpstate_board_task.get_future();
2402 std::thread(std::move(dumpstate_board_task)).detach();
2403
2404 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2405 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2406 if (!android::base::SetProperty(
2407 "ctl.interface_restart",
2408 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2409 MYLOGE("Couldn't restart dumpstate HAL\n");
2410 }
2411 }
2412 // Wait some time for init to kill dumpstate vendor HAL
2413 constexpr size_t killing_timeout_sec = 10;
2414 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2415 MYLOGE(
2416 "killing dumpstateBoard timed out after %zus, continue and "
2417 "there might be racing in content\n",
2418 killing_timeout_sec);
2419 }
2420}
2421
2422static void DoDumpstateBoardAidl(
2423 const std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal,
2424 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2425 const Dumpstate::BugreportMode bugreport_mode, const size_t timeout_sec) {
2426 MYLOGI("Using IDumpstateDevice AIDL HAL");
2427
2428 const char* descriptor_to_kill;
2429 using DumpstateBoardTask = std::packaged_task<bool()>;
2430 DumpstateBoardTask dumpstate_board_task;
2431 dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode dumpstate_hal_mode =
2432 GetDumpstateHalModeAidl(bugreport_mode);
2433
2434 descriptor_to_kill = dumpstate_hal_aidl::IDumpstateDevice::descriptor;
2435 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal, &dumpstate_fds, dumpstate_hal_mode,
2436 timeout_sec]() -> bool {
2437 auto status = dumpstate_hal->dumpstateBoard(dumpstate_fds, dumpstate_hal_mode, timeout_sec);
2438
2439 if (!status.isOk()) {
2440 MYLOGE("dumpstateBoard failed: %s\n", status.getDescription().c_str());
2441 return false;
2442 }
2443 return true;
2444 });
2445 auto result = dumpstate_board_task.get_future();
2446 std::thread(std::move(dumpstate_board_task)).detach();
2447
2448 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2449 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2450 if (!android::base::SetProperty(
2451 "ctl.interface_restart",
2452 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2453 MYLOGE("Couldn't restart dumpstate HAL\n");
2454 }
2455 }
2456 // Wait some time for init to kill dumpstate vendor HAL
2457 constexpr size_t killing_timeout_sec = 10;
2458 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2459 MYLOGE(
2460 "killing dumpstateBoard timed out after %zus, continue and "
2461 "there might be racing in content\n",
2462 killing_timeout_sec);
2463 }
2464}
2465
2466static std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> GetDumpstateBoardAidlService() {
2467 const std::string aidl_instance_name =
2468 std::string(dumpstate_hal_aidl::IDumpstateDevice::descriptor) + "/default";
2469
2470 if (!AServiceManager_isDeclared(aidl_instance_name.c_str())) {
2471 return nullptr;
2472 }
2473
2474 ndk::SpAIBinder dumpstateBinder(AServiceManager_waitForService(aidl_instance_name.c_str()));
2475
2476 return dumpstate_hal_aidl::IDumpstateDevice::fromBinder(dumpstateBinder);
2477}
2478
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002479void Dumpstate::DumpstateBoard(int out_fd) {
2480 dprintf(out_fd, "========================================================\n");
2481 dprintf(out_fd, "== Board\n");
2482 dprintf(out_fd, "========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08002483
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002484 /*
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002485 * mount debugfs for non-user builds with ro.product.debugfs_restrictions.enabled
Hridya Valsaraju51101602021-04-02 14:32:46 -07002486 * set to true and unmount it after invoking dumpstateBoard_* methods.
2487 * This is to enable debug builds to not have debugfs mounted during runtime.
2488 * It will also ensure that debugfs is only accessed by the dumpstate HAL.
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002489 */
Hridya Valsaraju51101602021-04-02 14:32:46 -07002490 auto mount_debugfs =
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002491 android::base::GetBoolProperty("ro.product.debugfs_restrictions.enabled", false);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002492 if (mount_debugfs) {
2493 RunCommand("mount debugfs", {"mount", "-t", "debugfs", "debugfs", "/sys/kernel/debug"},
2494 AS_ROOT_20);
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002495 RunCommand("chmod debugfs", {"chmod", "0755", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002496 }
2497
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002498 std::vector<std::string> paths;
2499 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07002500 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002501 paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
2502 kDumpstateBoardFiles[i].c_str()));
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002503 remover.emplace_back(android::base::make_scope_guard(
2504 std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002505 }
Jie Song9fbfad02017-06-20 16:29:42 -07002506
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002507 // get dumpstate HAL AIDL implementation
2508 std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal_handle_aidl(
2509 GetDumpstateBoardAidlService());
2510 if (dumpstate_hal_handle_aidl == nullptr) {
2511 MYLOGI("No IDumpstateDevice AIDL implementation\n");
2512 }
2513
2514 // get dumpstate HAL HIDL implementation, only if AIDL HAL implementation not found
2515 sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_handle_hidl_1_0 = nullptr;
2516 if (dumpstate_hal_handle_aidl == nullptr) {
2517 dumpstate_hal_handle_hidl_1_0 = dumpstate_hal_hidl_1_0::IDumpstateDevice::getService();
2518 if (dumpstate_hal_handle_hidl_1_0 == nullptr) {
2519 MYLOGI("No IDumpstateDevice HIDL implementation\n");
2520 }
2521 }
2522
2523 // if neither HIDL nor AIDL implementation found, then return
2524 if (dumpstate_hal_handle_hidl_1_0 == nullptr && dumpstate_hal_handle_aidl == nullptr) {
2525 MYLOGE("Could not find IDumpstateDevice implementation\n");
Wei Wang587eac92018-04-05 12:17:20 -07002526 return;
2527 }
2528
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002529 // this is used to hold the file descriptors and when this variable goes out of scope
2530 // the file descriptors are closed
2531 std::vector<::ndk::ScopedFileDescriptor> dumpstate_fds;
Wei Wang587eac92018-04-05 12:17:20 -07002532
Nandana Dutt5c390032019-03-12 10:52:56 +00002533 // TODO(128270426): Check for consent in between?
Wei Wang587eac92018-04-05 12:17:20 -07002534 for (size_t i = 0; i < paths.size(); i++) {
2535 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
2536
2537 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
2538 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
2539 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
2540 if (fd < 0) {
2541 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
2542 return;
2543 }
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002544
2545 dumpstate_fds.emplace_back(fd.release());
2546 // we call fd.release() here to make sure "fd" does not get closed
2547 // after "fd" goes out of scope after this block.
2548 // "fd" will be closed when "dumpstate_fds" goes out of scope
2549 // i.e. when we exit this function
Wei Wang587eac92018-04-05 12:17:20 -07002550 }
2551
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002552 // Given that bugreport is required to diagnose failures, it's better to set an arbitrary amount
2553 // of timeout for IDumpstateDevice than to block the rest of bugreport. In the timeout case, we
2554 // will kill the HAL and grab whatever it dumped in time.
Michael Eastwood8523ea02022-03-10 16:33:08 -08002555 constexpr size_t timeout_sec = 45;
Wei Wang587eac92018-04-05 12:17:20 -07002556
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002557 if (dumpstate_hal_handle_aidl != nullptr) {
2558 DoDumpstateBoardAidl(dumpstate_hal_handle_aidl, dumpstate_fds, options_->bugreport_mode,
2559 timeout_sec);
2560 } else if (dumpstate_hal_handle_hidl_1_0 != nullptr) {
2561 // run HIDL HAL only if AIDL HAL not found
2562 DoDumpstateBoardHidl(dumpstate_hal_handle_hidl_1_0, dumpstate_fds, options_->bugreport_mode,
2563 timeout_sec);
Wei Wang587eac92018-04-05 12:17:20 -07002564 }
2565
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002566 if (mount_debugfs) {
Hridya Valsaraju51101602021-04-02 14:32:46 -07002567 auto keep_debugfs_mounted =
2568 android::base::GetProperty("persist.dbg.keep_debugfs_mounted", "");
2569 if (keep_debugfs_mounted.empty())
2570 RunCommand("unmount debugfs", {"umount", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002571 }
2572
Wei Wang587eac92018-04-05 12:17:20 -07002573 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
2574 for (size_t i = 0; i < paths.size(); i++) {
2575 struct stat s;
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002576 if (fstat(dumpstate_fds[i].get(), &s) == -1) {
2577 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(), strerror(errno));
Wei Wang587eac92018-04-05 12:17:20 -07002578 file_sizes[i] = -1;
2579 continue;
2580 }
2581 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002582 }
2583
2584 for (size_t i = 0; i < paths.size(); i++) {
2585 if (file_sizes[i] == -1) {
2586 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002587 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002588 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07002589 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002590 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002591 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002592 remover[i].Disable();
2593 EnqueueAddZipEntryAndCleanupIfNeeded(kDumpstateBoardFiles[i], paths[i]);
2594 dprintf(out_fd, "*** See %s entry ***\n", kDumpstateBoardFiles[i].c_str());
Jie Song9fbfad02017-06-20 16:29:42 -07002595 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08002596}
2597
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002598static void ShowUsage() {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002599 fprintf(stderr,
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002600 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o directory] [-p] "
2601 "[-s] [-S] [-q] [-P] [-R] [-L] [-V version]\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002602 " -h: display this help message\n"
2603 " -b: play sound file instead of vibrate, at beginning of job\n"
2604 " -e: play sound file instead of vibrate, at end of job\n"
mhasank2d75c442020-06-11 15:05:25 -07002605 " -o: write to custom directory (only in limited mode)\n"
Abhijeet Kaurbb55a3b2019-06-13 18:07:25 +01002606 " -p: capture screenshot to filename.png\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002607 " -s: write zipped file to control socket (for init)\n"
2608 " -S: write file location to control socket (for init)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002609 " -q: disable vibrate\n"
Abhijeet Kaure370d682019-10-01 16:49:30 +01002610 " -P: send broadcast when started and do progress updates\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002611 " -R: take bugreport in remote mode (shouldn't be used with -P)\n"
Nandana Dutt235864b2019-01-22 12:10:16 +00002612 " -w: start binder service and make it wait for a call to startBugreport\n"
mhasankd451a472020-05-26 18:02:39 -07002613 " -L: output limited information that is safe for submission in feedback reports\n"
Felipe Lemed071c682016-10-20 16:48:00 -07002614 " -v: prints the dumpstate header and exit\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002615}
2616
Wei Liuf87959e2016-08-26 14:51:42 -07002617static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07002618 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07002619}
2620
Felipe Leme1d486fe2016-10-14 18:06:47 -07002621bool Dumpstate::FinishZipFile() {
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002622 // Runs all enqueued adding zip entry and cleanup tasks before finishing the zip file.
2623 if (zip_entry_tasks_) {
2624 zip_entry_tasks_->run(/* do_cancel = */false);
2625 }
2626
Felipe Leme9a523ae2016-10-20 15:10:33 -07002627 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07002628 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07002629 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002630 // Final timestamp
2631 char date[80];
2632 time_t the_real_now_please_stand_up = time(nullptr);
2633 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002634 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002635 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002636
Felipe Leme9a523ae2016-10-20 15:10:33 -07002637 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002638 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08002639 return false;
2640 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07002641 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002642 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08002643 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08002644 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08002645
Felipe Leme0f3fb202016-06-10 17:10:53 -07002646 // Add log file (which contains stderr output) to zip...
2647 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002648 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07002649 MYLOGE("Failed to add dumpstate log to .zip file\n");
2650 return false;
2651 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002652 // TODO: Should truncate the existing file.
2653 // ... and re-open it for further logging.
Nandana Dutta344cb62019-02-22 15:12:35 +00002654 if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
2655 return false;
2656 }
Felipe Leme0f3fb202016-06-10 17:10:53 -07002657 fprintf(stderr, "\n");
2658
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002659 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07002660 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002661 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002662 return false;
2663 }
2664
Felipe Leme1d486fe2016-10-14 18:06:47 -07002665 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
2666 ds.zip_file.reset(nullptr);
2667
Felipe Lemee9d2c542016-11-15 11:48:26 -08002668 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002669 android::os::UnlinkAndLogOnError(tmp_path_);
Felipe Lemec4eee562016-04-21 15:42:55 -07002670
Felipe Leme1e9edc62015-12-21 16:02:13 -08002671 return true;
2672}
Felipe Leme6e01fa62015-11-11 19:35:14 -08002673
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00002674static void SendBroadcast(const std::string& action,
2675 const std::vector<std::string>& args,
2676 int32_t user_id) {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002677 // clang-format off
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00002678 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user",
2679 std::to_string(user_id), "--receiver-foreground",
2680 "--receiver-include-background", "-a", action};
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002681 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08002682
2683 am.insert(am.end(), args.begin(), args.end());
2684
Felipe Leme8d2410e2017-02-08 09:46:08 -08002685 RunCommand("", am,
2686 CommandOptions::WithTimeout(20)
2687 .Log("Sending broadcast: '%s'\n")
2688 .Always()
2689 .DropRoot()
2690 .RedirectStderr()
2691 .Build());
2692}
2693
Felipe Leme35b8cf12017-02-10 15:47:29 -08002694static void Vibrate(int duration_ms) {
2695 // clang-format off
Lais Andrade51156962021-02-22 19:21:35 +00002696 std::vector<std::string> args = {"cmd", "vibrator_manager", "synced", "-f", "-d", "dumpstate",
2697 "oneshot", std::to_string(duration_ms)};
2698 RunCommand("", args,
Felipe Leme35b8cf12017-02-10 15:47:29 -08002699 CommandOptions::WithTimeout(10)
2700 .Log("Vibrate: '%s'\n")
2701 .Always()
2702 .Build());
2703 // clang-format on
2704}
2705
Nandana Dutt979388e2018-11-30 16:48:55 +00002706static void MaybeResolveSymlink(std::string* path) {
2707 std::string resolved_path;
2708 if (android::base::Readlink(*path, &resolved_path)) {
2709 *path = resolved_path;
2710 }
2711}
2712
Nandana Dutt4be45d12018-09-26 15:04:23 +01002713/*
2714 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002715 * and adds the version file. Return false if zip_file could not be open to write.
Nandana Dutt4be45d12018-09-26 15:04:23 +01002716 */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002717static bool PrepareToWriteToFile() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002718 MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2719
Nandana Dutt4be45d12018-09-26 15:04:23 +01002720 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2721 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002722 ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002723 char date[80];
2724 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2725 ds.name_ = date;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002726
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002727 if (ds.options_->telephony_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002728 ds.base_name_ += "-telephony";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002729 } else if (ds.options_->wifi_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002730 ds.base_name_ += "-wifi";
2731 }
2732
Paul Chang0d2aad72020-02-13 20:04:03 +08002733 if (ds.options_->do_screenshot) {
Nandana Dutt9d17b942020-03-26 10:02:59 +00002734 ds.screenshot_path_ = ds.GetPath(ds.CalledByApi() ? "-png.tmp" : ".png");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002735 }
2736 ds.tmp_path_ = ds.GetPath(".tmp");
2737 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2738
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01002739 std::string destination = ds.CalledByApi()
Nandana Dutt54dbd672019-01-11 12:58:05 +00002740 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
Nandana Dutt9a76d202019-01-21 15:56:48 +00002741 : ds.bugreport_internal_dir_.c_str();
Nandana Dutt4be45d12018-09-26 15:04:23 +01002742 MYLOGD(
Nandana Dutt235c6672019-11-14 15:22:32 +00002743 "Bugreport dir: [%s] "
2744 "Base name: [%s] "
2745 "Suffix: [%s] "
2746 "Log path: [%s] "
2747 "Temporary path: [%s] "
2748 "Screenshot path: [%s]\n",
Nandana Dutt9a76d202019-01-21 15:56:48 +00002749 destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2750 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002751
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002752 ds.path_ = ds.GetPath(ds.CalledByApi() ? "-zip.tmp" : ".zip");
2753 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2754 create_parent_dirs(ds.path_.c_str());
2755 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2756 if (ds.zip_file == nullptr) {
2757 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2758 return false;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002759 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002760 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2761 ds.AddTextZipEntry("version.txt", ds.version_);
2762 return true;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002763}
2764
2765/*
Abhijeet Kaure370d682019-10-01 16:49:30 +01002766 * Finalizes writing to the file by zipping the tmp file to the final location,
Nandana Dutt4be45d12018-09-26 15:04:23 +01002767 * printing zipped file status, etc.
2768 */
2769static void FinalizeFile() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002770 bool do_text_file = !ds.FinishZipFile();
2771 if (do_text_file) {
2772 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002773 }
mhasank2d75c442020-06-11 15:05:25 -07002774
2775 std::string final_path = ds.path_;
2776 if (ds.options_->OutputToCustomFile()) {
mhasank3a4cfb42020-06-15 18:06:43 -07002777 final_path = ds.GetPath(ds.options_->out_dir, ".zip");
mhasank2d75c442020-06-11 15:05:25 -07002778 android::os::CopyFileToFile(ds.path_, final_path);
2779 }
2780
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002781 if (ds.options_->stream_to_socket) {
2782 android::os::CopyFileToFd(ds.path_, ds.control_socket_fd_);
2783 } else if (ds.options_->progress_updates_to_socket) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002784 if (do_text_file) {
2785 dprintf(ds.control_socket_fd_,
2786 "FAIL:could not create zip file, check %s "
2787 "for more details\n",
2788 ds.log_path_.c_str());
2789 } else {
mhasank2d75c442020-06-11 15:05:25 -07002790 dprintf(ds.control_socket_fd_, "OK:%s\n", final_path.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002791 }
2792 }
2793}
2794
Nandana Dutt4be45d12018-09-26 15:04:23 +01002795
Nandana Dutt58d72e22018-11-16 10:30:48 +00002796static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2797 switch (mode) {
2798 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2799 return "BUGREPORT_FULL";
2800 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2801 return "BUGREPORT_INTERACTIVE";
2802 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2803 return "BUGREPORT_REMOTE";
2804 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2805 return "BUGREPORT_WEAR";
2806 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2807 return "BUGREPORT_TELEPHONY";
2808 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2809 return "BUGREPORT_WIFI";
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002810 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2811 return "BUGREPORT_DEFAULT";
Nandana Dutt58d72e22018-11-16 10:30:48 +00002812 }
2813}
2814
Steven Leeb573eb82022-11-29 22:31:35 +08002815static bool IsConsentlessBugreportAllowed(const Dumpstate::DumpOptions& options) {
2816 // only BUGREPORT_TELEPHONY does not allow using consentless bugreport
2817 return !options.telephony_only;
2818}
2819
Paul Changf59c2b72020-03-10 02:08:55 +08002820static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options,
2821 bool is_screenshot_requested) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002822 // Modify com.android.shell.BugreportProgressService#isDefaultScreenshotRequired as well for
2823 // default system screenshots.
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002824 options->bugreport_mode = mode;
2825 options->bugreport_mode_string = ModeToString(mode);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002826 switch (mode) {
2827 case Dumpstate::BugreportMode::BUGREPORT_FULL:
Paul Changf59c2b72020-03-10 02:08:55 +08002828 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002829 break;
2830 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002831 // Currently, the dumpstate binder is only used by Shell to update progress.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002832 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002833 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002834 break;
2835 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002836 options->do_vibrate = false;
2837 options->is_remote_mode = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002838 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002839 break;
2840 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
Robert Ginda55ecebd2023-04-03 22:53:13 +00002841 options->do_vibrate = false;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002842 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002843 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002844 break;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002845 // TODO(b/148168577) rename TELEPHONY everywhere to CONNECTIVITY.
Nandana Dutt58d72e22018-11-16 10:30:48 +00002846 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002847 options->telephony_only = true;
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002848 options->do_progress_updates = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002849 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002850 break;
2851 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002852 options->wifi_only = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002853 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002854 break;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002855 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2856 break;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002857 }
2858}
2859
Nandana Dutt58d72e22018-11-16 10:30:48 +00002860static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
Nandana Dutt235c6672019-11-14 15:22:32 +00002861 MYLOGI(
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002862 "do_vibrate: %d stream_to_socket: %d progress_updates_to_socket: %d do_screenshot: %d "
Rhed Jao25f50e02020-08-20 00:10:32 +08002863 "is_remote_mode: %d show_header_only: %d telephony_only: %d "
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002864 "wifi_only: %d do_progress_updates: %d fd: %d bugreport_mode: %s "
mhasankd451a472020-05-26 18:02:39 -07002865 "limited_only: %d args: %s\n",
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002866 options.do_vibrate, options.stream_to_socket, options.progress_updates_to_socket,
Paul Chang0d2aad72020-02-13 20:04:03 +08002867 options.do_screenshot, options.is_remote_mode, options.show_header_only,
Rhed Jao25f50e02020-08-20 00:10:32 +08002868 options.telephony_only, options.wifi_only,
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002869 options.do_progress_updates, options.bugreport_fd.get(),
2870 options.bugreport_mode_string.c_str(),
2871 options.limited_only, options.args.c_str());
Nandana Dutt58d72e22018-11-16 10:30:48 +00002872}
2873
Nandana Dutt54dbd672019-01-11 12:58:05 +00002874void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
Kean Mariotti306633e2022-09-05 16:30:47 +00002875 int bugreport_flags,
Nandana Dutt54dbd672019-01-11 12:58:05 +00002876 const android::base::unique_fd& bugreport_fd_in,
Paul Changf59c2b72020-03-10 02:08:55 +08002877 const android::base::unique_fd& screenshot_fd_in,
2878 bool is_screenshot_requested) {
Kean Mariotti306633e2022-09-05 16:30:47 +00002879 this->use_predumped_ui_data = bugreport_flags & BugreportFlag::BUGREPORT_USE_PREDUMPED_UI_DATA;
Gavin Corkerya44686c2022-11-23 18:16:51 +00002880 this->is_consent_deferred = bugreport_flags & BugreportFlag::BUGREPORT_FLAG_DEFER_CONSENT;
Nandana Dutt54dbd672019-01-11 12:58:05 +00002881 // Duplicate the fds because the passed in fds don't outlive the binder transaction.
Todd Frederick621533f2022-03-26 02:54:17 +00002882 bugreport_fd.reset(fcntl(bugreport_fd_in.get(), F_DUPFD_CLOEXEC, 0));
2883 screenshot_fd.reset(fcntl(screenshot_fd_in.get(), F_DUPFD_CLOEXEC, 0));
Nandana Dutt58d72e22018-11-16 10:30:48 +00002884
Paul Changf59c2b72020-03-10 02:08:55 +08002885 SetOptionsFromMode(bugreport_mode, this, is_screenshot_requested);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002886}
2887
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002888Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
2889 RunStatus status = RunStatus::OK;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002890 int c;
mhasankd451a472020-05-26 18:02:39 -07002891 while ((c = getopt(argc, argv, "dho:svqzpLPBRSV:w")) != -1) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002892 switch (c) {
2893 // clang-format off
mhasank3a4cfb42020-06-15 18:06:43 -07002894 case 'o': out_dir = optarg; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002895 case 's': stream_to_socket = true; break;
2896 case 'S': progress_updates_to_socket = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002897 case 'v': show_header_only = true; break;
2898 case 'q': do_vibrate = false; break;
Paul Chang0d2aad72020-02-13 20:04:03 +08002899 case 'p': do_screenshot = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002900 case 'P': do_progress_updates = true; break;
2901 case 'R': is_remote_mode = true; break;
mhasankd451a472020-05-26 18:02:39 -07002902 case 'L': limited_only = true; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002903 case 'V':
2904 case 'd':
2905 case 'z':
2906 // compatibility no-op
2907 break;
Nandana Dutt235864b2019-01-22 12:10:16 +00002908 case 'w':
2909 // This was already processed
2910 break;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002911 case 'h':
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002912 status = RunStatus::HELP;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002913 break;
2914 default:
2915 fprintf(stderr, "Invalid option: %c\n", c);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002916 status = RunStatus::INVALID_INPUT;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002917 break;
2918 // clang-format on
2919 }
2920 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08002921
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002922 for (int i = 0; i < argc; i++) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002923 args += argv[i];
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002924 if (i < argc - 1) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002925 args += " ";
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002926 }
2927 }
2928
2929 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
2930 optind = 1;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002931
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002932 return status;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002933}
2934
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002935bool Dumpstate::DumpOptions::ValidateOptions() const {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002936 if (bugreport_fd.get() != -1 && stream_to_socket) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002937 return false;
2938 }
2939
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002940 if ((progress_updates_to_socket || do_progress_updates) && stream_to_socket) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002941 return false;
2942 }
2943
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002944 if (is_remote_mode && (do_progress_updates || stream_to_socket)) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002945 return false;
2946 }
2947 return true;
2948}
2949
Nandana Dutt197661d2018-11-16 16:40:21 +00002950void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
2951 options_ = std::move(options);
2952}
2953
Abhijeet Kaura407fb82020-03-27 12:51:12 +00002954void Dumpstate::Initialize() {
2955 /* gets the sequential id */
2956 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
2957 id_ = ++last_id;
2958 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
2959}
2960
Nandana Duttd2f5f082019-01-18 17:13:52 +00002961Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
2962 Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
Gavin Corkerya44686c2022-11-23 18:16:51 +00002963 HandleRunStatus(status);
2964 return status;
2965}
2966
2967Dumpstate::RunStatus Dumpstate::Retrieve(int32_t calling_uid, const std::string& calling_package) {
2968 Dumpstate::RunStatus status = RetrieveInternal(calling_uid, calling_package);
2969 HandleRunStatus(status);
2970 return status;
2971}
2972
2973Dumpstate::RunStatus Dumpstate::RetrieveInternal(int32_t calling_uid,
2974 const std::string& calling_package) {
2975 consent_callback_ = new ConsentCallback();
2976 const String16 incidentcompanion("incidentcompanion");
2977 sp<android::IBinder> ics(
2978 defaultServiceManager()->checkService(incidentcompanion));
2979 android::String16 package(calling_package.c_str());
2980 if (ics != nullptr) {
2981 MYLOGD("Checking user consent via incidentcompanion service\n");
2982 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
2983 calling_uid, package, String16(), String16(),
2984 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
2985 } else {
2986 MYLOGD(
2987 "Unable to check user consent; incidentcompanion service unavailable\n");
2988 return RunStatus::USER_CONSENT_TIMED_OUT;
2989 }
2990 UserConsentResult consent_result = consent_callback_->getResult();
2991 int timeout_ms = 30 * 1000;
2992 while (consent_result == UserConsentResult::UNAVAILABLE &&
2993 consent_callback_->getElapsedTimeMs() < timeout_ms) {
2994 sleep(1);
2995 consent_result = consent_callback_->getResult();
2996 }
2997 if (consent_result == UserConsentResult::DENIED) {
2998 return RunStatus::USER_CONSENT_DENIED;
2999 }
3000 if (consent_result == UserConsentResult::UNAVAILABLE) {
3001 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3002 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3003 consent_callback_.get());
3004 return RunStatus::USER_CONSENT_TIMED_OUT;
3005 }
3006
3007 bool copy_succeeded =
3008 android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
3009 if (copy_succeeded) {
3010 android::os::UnlinkAndLogOnError(path_);
3011 }
3012 return copy_succeeded ? Dumpstate::RunStatus::OK
3013 : Dumpstate::RunStatus::ERROR;
3014}
3015
3016void Dumpstate::HandleRunStatus(Dumpstate::RunStatus status) {
3017 if (listener_ != nullptr) {
Nandana Duttbabf6c72019-01-15 14:11:12 +00003018 switch (status) {
3019 case Dumpstate::RunStatus::OK:
Gavin Corkerya44686c2022-11-23 18:16:51 +00003020 listener_->onFinished(path_.c_str());
Nandana Duttbabf6c72019-01-15 14:11:12 +00003021 break;
3022 case Dumpstate::RunStatus::HELP:
3023 break;
3024 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003025 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00003026 break;
3027 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003028 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
3029 break;
3030 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3031 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
3032 break;
3033 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
3034 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00003035 break;
3036 }
3037 }
Nandana Duttbabf6c72019-01-15 14:11:12 +00003038}
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003039void Dumpstate::Cancel() {
3040 CleanupTmpFiles();
3041 android::os::UnlinkAndLogOnError(log_path_);
3042 for (int i = 0; i < NUM_OF_DUMPS; i++) {
3043 android::os::UnlinkAndLogOnError(ds.bugreport_internal_dir_ + "/" +
3044 kDumpstateBoardFiles[i]);
3045 }
3046 tombstone_data_.clear();
3047 anr_data_.clear();
Woody Lin20767a92022-11-29 15:50:24 +08003048 shutdown_checkpoints_.clear();
Rhed Jao0daac912020-08-21 14:48:20 +08003049
3050 // Instead of shutdown the pool, we delete temporary files directly since
3051 // shutdown blocking the call.
3052 if (dump_pool_) {
3053 dump_pool_->deleteTempFiles();
3054 }
3055 if (zip_entry_tasks_) {
3056 zip_entry_tasks_->run(/*do_cancel =*/ true);
3057 }
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003058}
3059
Kean Mariotti306633e2022-09-05 16:30:47 +00003060void Dumpstate::PreDumpUiData() {
3061 MaybeSnapshotUiTraces();
3062}
3063
Nandana Dutt979388e2018-11-30 16:48:55 +00003064/*
3065 * Dumps relevant information to a bugreport based on the given options.
3066 *
3067 * The bugreport can be dumped to a file or streamed to a socket.
3068 *
3069 * How dumping to file works:
3070 * stdout is redirected to a temporary file. This will later become the main bugreport entry.
3071 * stderr is redirected a log file.
3072 *
3073 * The temporary bugreport is then populated via printfs, dumping contents of files and
3074 * output of commands to stdout.
3075 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003076 * A bunch of other files and dumps are added to the zip archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00003077 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003078 * The temporary bugreport file and the log file also get added to the archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00003079 *
mhasank2d75c442020-06-11 15:05:25 -07003080 * Bugreports are first generated in a local directory and later copied to the caller's fd
3081 * or directory if supplied.
Nandana Dutt979388e2018-11-30 16:48:55 +00003082 */
Nandana Duttd2f5f082019-01-18 17:13:52 +00003083Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
3084 const std::string& calling_package) {
Rhed Jao5377d792020-07-16 17:37:39 +08003085 DurationReporter duration_reporter("RUN INTERNAL", /* logcat_only = */true);
Nandana Dutt979388e2018-11-30 16:48:55 +00003086 LogDumpOptions(*options_);
Nandana Dutt197661d2018-11-16 16:40:21 +00003087 if (!options_->ValidateOptions()) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00003088 MYLOGE("Invalid options specified\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003089 return RunStatus::INVALID_INPUT;
3090 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003091 /* set as high priority, and protect from OOM killer */
3092 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003093
Felipe Lemed071c682016-10-20 16:48:00 -07003094 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07003095 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003096 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003097 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07003098 } else {
3099 /* fallback to kernels <= 2.6.35 */
3100 oom_adj = fopen("/proc/self/oom_adj", "we");
3101 if (oom_adj) {
3102 fputs("-17", oom_adj);
3103 fclose(oom_adj);
3104 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003105 }
3106
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003107 if (version_ == VERSION_DEFAULT) {
3108 version_ = VERSION_CURRENT;
Michal Karpinski4db754f2015-12-11 18:04:32 +00003109 }
3110
Chris Morin5a50d482022-02-01 17:41:18 -08003111 if (version_ != VERSION_CURRENT) {
3112 MYLOGE("invalid version requested ('%s'); supported values are: ('%s', '%s')\n",
3113 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003114 return RunStatus::INVALID_INPUT;
Felipe Lemed071c682016-10-20 16:48:00 -07003115 }
3116
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003117 if (options_->show_header_only) {
3118 PrintHeader();
3119 return RunStatus::OK;
Felipe Lemed071c682016-10-20 16:48:00 -07003120 }
3121
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003122 MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n",
3123 calling_uid, calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003124
Felipe Leme7447d7c2016-11-03 18:12:22 -07003125 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003126 std::string stats_path =
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003127 android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003128 progress_.reset(new Progress(stats_path));
Felipe Leme7447d7c2016-11-03 18:12:22 -07003129
Sahana Raof35ed432019-07-12 10:47:52 +01003130 if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
3131 MYLOGE("Failed to acquire wake lock: %s\n", strerror(errno));
3132 } else {
3133 // Wake lock will be released automatically on process death
3134 MYLOGD("Wake lock acquired.\n");
3135 }
3136
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08003137 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07003138
Felipe Lemef0292972016-11-22 13:57:05 -08003139 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07003140 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
3141 }
3142
Kevin Jeonfa64e642023-07-27 11:36:41 -04003143 if (PropertiesHelper::IsStrictRun()) {
3144 MYLOGI(
3145 "Running on strict-run mode, which has shorter timeouts "
3146 "(to disable, call 'setprop dumpstate.strict_run false')\n");
3147 }
3148
Nandana Dutt235c6672019-11-14 15:22:32 +00003149 MYLOGI("dumpstate info: id=%d, args='%s', bugreport_mode= %s bugreport format version: %s\n",
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00003150 id_, options_->args.c_str(), options_->bugreport_mode_string.c_str(), version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08003151
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003152 do_early_screenshot_ = options_->do_progress_updates;
Felipe Lemee338bf62015-12-07 14:03:50 -08003153
Christopher Ferrised9354f2014-10-01 17:35:01 -07003154 // If we are going to use a socket, do it as early as possible
3155 // to avoid timeouts from bugreport.
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003156 if (options_->stream_to_socket || options_->progress_updates_to_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07003157 MYLOGD("Opening control socket\n");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003158 control_socket_fd_ = open_socket_fn_("dumpstate");
Nandana Dutta344cb62019-02-22 15:12:35 +00003159 if (control_socket_fd_ == -1) {
3160 return ERROR;
3161 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003162 if (options_->progress_updates_to_socket) {
3163 options_->do_progress_updates = 1;
3164 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07003165 }
3166
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003167 if (!PrepareToWriteToFile()) {
3168 return ERROR;
3169 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08003170
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003171 // Interactive, wear & telephony modes are default to true.
3172 // and may enable from cli option or when using control socket
3173 if (options_->do_progress_updates) {
3174 // clang-format off
3175 std::vector<std::string> am_args = {
3176 "--receiver-permission", "android.permission.DUMP",
3177 };
3178 // clang-format on
3179 // Send STARTED broadcast for apps that listen to bugreport generation events
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003180 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED",
3181 am_args, multiuser_get_user_id(calling_uid));
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003182 if (options_->progress_updates_to_socket) {
3183 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08003184 }
3185 }
3186
Nick Kralevichf3599b32016-01-25 15:05:16 -08003187 /* read /proc/cmdline before dropping root */
3188 FILE *cmdline = fopen("/proc/cmdline", "re");
3189 if (cmdline) {
3190 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
3191 fclose(cmdline);
3192 }
3193
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003194 if (options_->do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08003195 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05003196 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003197
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003198 if (zip_file != nullptr) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003199 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
3200 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003201 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08003202 }
3203 }
3204
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003205 int dup_stdout_fd;
3206 int dup_stderr_fd;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003207 // Redirect stderr to log_path_ for debugging.
3208 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
3209 if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
3210 return ERROR;
3211 }
3212 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
3213 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
3214 strerror(errno));
3215 }
Nandana Dutt979388e2018-11-30 16:48:55 +00003216
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003217 // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
3218 // moved into zip file later, if zipping.
3219 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
3220 // TODO: why not write to a file instead of stdout to overcome this problem?
3221 /* TODO: rather than generating a text file now and zipping it later,
3222 it would be more efficient to redirect stdout to the zip entry
3223 directly, but the libziparchive doesn't support that option yet. */
3224 if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
3225 return ERROR;
3226 }
3227 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
3228 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
3229 tmp_path_.c_str(), strerror(errno));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003230 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08003231
3232 // Don't buffer stdout
3233 setvbuf(stdout, nullptr, _IONBF, 0);
3234
Rhed Jao5377d792020-07-16 17:37:39 +08003235 // Enable the parallel run if the client requests to output to a file.
3236 EnableParallelRunIfNeeded();
3237 // Using scope guard to make sure the dump pool can be shut down correctly.
3238 auto scope_guard_to_shutdown_pool = android::base::make_scope_guard([=]() {
3239 ShutdownDumpPool();
3240 });
3241
Felipe Leme608385d2016-02-01 10:35:38 -08003242 // NOTE: there should be no stdout output until now, otherwise it would break the header.
3243 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08003244 // duration is logged into MYLOG instead.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003245 PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003246
Gavin Corkery6968f552020-11-22 18:09:05 +00003247 bool is_dumpstate_restricted = options_->telephony_only
3248 || options_->wifi_only
3249 || options_->limited_only;
3250 if (!is_dumpstate_restricted) {
Paul Chang0d2aad72020-02-13 20:04:03 +08003251 // Invoke critical dumpsys first to preserve system state, before doing anything else.
Jichao Lie89d9c12019-11-21 19:02:51 -08003252 RunDumpsysCritical();
Gavin Corkery6968f552020-11-22 18:09:05 +00003253 }
3254 MaybeTakeEarlyScreenshot();
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003255
3256 if (!is_dumpstate_restricted) {
3257 // Snapshot the system trace now (if running) to avoid that dumpstate's
3258 // own activity pushes out interesting data from the trace ring buffer.
3259 // The trace file is added to the zip by MaybeAddSystemTraceToZip().
3260 MaybeSnapshotSystemTrace();
Yohei Yukawa95305b32021-03-09 07:54:27 -08003261
Kean Mariotti306633e2022-09-05 16:30:47 +00003262 // Snapshot the UI traces now (if running).
3263 // The trace files will be added to bugreport later.
3264 MaybeSnapshotUiTraces();
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003265 }
Gavin Corkery6968f552020-11-22 18:09:05 +00003266 onUiIntensiveBugreportDumpsFinished(calling_uid);
3267 MaybeCheckUserConsent(calling_uid, calling_package);
3268 if (options_->telephony_only) {
3269 DumpstateTelephonyOnly(calling_package);
3270 } else if (options_->wifi_only) {
3271 DumpstateWifiOnly();
3272 } else if (options_->limited_only) {
3273 DumpstateLimitedOnly();
3274 } else {
Nandana Dutt4be45d12018-09-26 15:04:23 +01003275 // Dump state for the default case. This also drops root.
Jichao Lie89d9c12019-11-21 19:02:51 -08003276 RunStatus s = DumpstateDefaultAfterCritical();
Nandana Dutt5c390032019-03-12 10:52:56 +00003277 if (s != RunStatus::OK) {
Nandana Duttaac6f582019-07-26 14:32:47 +01003278 if (s == RunStatus::USER_CONSENT_DENIED) {
Nandana Dutt5c390032019-03-12 10:52:56 +00003279 HandleUserConsentDenied();
3280 }
3281 return s;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08003282 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07003283 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07003284
Felipe Leme55b42a62015-11-10 17:39:08 -08003285 /* close output if needed */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003286 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003287
Abhijeet Kaure370d682019-10-01 16:49:30 +01003288 // Zip the (now complete) .tmp file within the internal directory.
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003289 ATRACE_BEGIN("FinalizeFile");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003290 FinalizeFile();
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003291 ATRACE_END();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003292
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003293 // Share the final file with the caller if the user has consented or Shell is the caller.
Nandana Duttd2f5f082019-01-18 17:13:52 +00003294 Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
Gavin Corkerya44686c2022-11-23 18:16:51 +00003295 if (CalledByApi() && !options_->is_consent_deferred) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003296 status = CopyBugreportIfUserConsented(calling_uid);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003297 if (status != Dumpstate::RunStatus::OK &&
3298 status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3299 // Do an early return if there were errors. We make an exception for consent
3300 // timing out because it's possible the user got distracted. In this case the
3301 // bugreport is not shared but made available for manual retrieval.
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003302 MYLOGI("User denied consent. Returning\n");
Nandana Duttd2f5f082019-01-18 17:13:52 +00003303 return status;
3304 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003305 if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3306 MYLOGI(
3307 "Did not receive user consent yet."
3308 " Will not copy the bugreport artifacts to caller.\n");
Abhijeet Kaur57627412019-04-17 16:00:09 +01003309 const String16 incidentcompanion("incidentcompanion");
3310 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
3311 if (ics != nullptr) {
3312 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3313 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3314 consent_callback_.get());
3315 } else {
3316 MYLOGD("Unable to cancel user consent; incidentcompanion service unavailable\n");
3317 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003318 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003319 }
3320
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003321 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003322 if (options_->do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09003323 for (int i = 0; i < 3; i++) {
3324 Vibrate(75);
3325 usleep((75 + 50) * 1000);
3326 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003327 }
3328
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003329 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
3330 progress_->GetInitialMax());
3331 progress_->Save();
3332 MYLOGI("done (id %d)\n", id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003333
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003334 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08003335
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003336 if (control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07003337 MYLOGD("Closing control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003338 close(control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07003339 }
3340
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003341 tombstone_data_.clear();
3342 anr_data_.clear();
Woody Lin20767a92022-11-29 15:50:24 +08003343 shutdown_checkpoints_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01003344
Nandana Duttd2f5f082019-01-18 17:13:52 +00003345 return (consent_callback_ != nullptr &&
3346 consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
3347 ? USER_CONSENT_TIMED_OUT
3348 : RunStatus::OK;
3349}
3350
Paul Chang0d2aad72020-02-13 20:04:03 +08003351void Dumpstate::MaybeTakeEarlyScreenshot() {
3352 if (!options_->do_screenshot || !do_early_screenshot_) {
3353 return;
3354 }
3355
3356 TakeScreenshot();
3357}
3358
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003359void Dumpstate::MaybeSnapshotSystemTrace() {
3360 // If a background system trace is happening and is marked as "suitable for
3361 // bugreport" (i.e. bugreport_score > 0 in the trace config), this command
3362 // will stop it and serialize into SYSTEM_TRACE_SNAPSHOT. In the (likely)
3363 // case that no trace is ongoing, this command is a no-op.
3364 // Note: this should not be enqueued as we need to freeze the trace before
3365 // dumpstate starts. Otherwise the trace ring buffers will contain mostly
3366 // the dumpstate's own activity which is irrelevant.
3367 int res = RunCommand(
3368 "SERIALIZE PERFETTO TRACE",
3369 {"perfetto", "--save-for-bugreport"},
3370 CommandOptions::WithTimeout(10)
3371 .DropRoot()
3372 .CloseAllFileDescriptorsOnExec()
3373 .Build());
3374 has_system_trace_ = res == 0;
3375 // MaybeAddSystemTraceToZip() will take care of copying the trace in the zip
3376 // file in the later stages.
3377}
3378
Kean Mariotti306633e2022-09-05 16:30:47 +00003379void Dumpstate::MaybeSnapshotUiTraces() {
3380 if (PropertiesHelper::IsUserBuild() || options_->use_predumped_ui_data) {
3381 return;
3382 }
Hongwei Wang9ec5c252023-01-24 15:09:59 -08003383
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003384 const std::vector<std::vector<std::string>> dumpTracesForBugReportCommands = {
3385 {"dumpsys", "activity", "service", "SystemUIService", "WMShell", "protolog",
3386 "save-for-bugreport"},
3387 {"dumpsys", "activity", "service", "SystemUIService", "WMShell", "transitions", "tracing",
3388 "save-for-bugreport"},
3389 {"cmd", "input_method", "tracing", "save-for-bugreport"},
3390 {"cmd", "window", "tracing", "save-for-bugreport"},
3391 {"cmd", "window", "shell", "tracing", "save-for-bugreport"},
3392 };
Hongwei Wang39229132023-01-24 15:09:59 -08003393
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003394 for (const auto& command : dumpTracesForBugReportCommands) {
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003395 RunCommand(
3396 // Empty name because it's not intended to be classified as a bugreport section.
3397 // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003398 "", command,
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003399 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
3400 }
Kean Mariotti306633e2022-09-05 16:30:47 +00003401
Pablo Gamitoefdc5922023-04-19 09:44:47 +00003402 // This command needs to be run as root
Kean Mariotti306633e2022-09-05 16:30:47 +00003403 static const auto SURFACEFLINGER_COMMAND_SAVE_ALL_TRACES = std::vector<std::string> {
3404 "service", "call", "SurfaceFlinger", "1042"
3405 };
3406 // Empty name because it's not intended to be classified as a bugreport section.
3407 // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
3408 RunCommand(
3409 "", SURFACEFLINGER_COMMAND_SAVE_ALL_TRACES,
3410 CommandOptions::WithTimeout(10).Always().AsRoot().RedirectStderr().Build());
3411}
3412
3413void Dumpstate::MaybePostProcessUiTraces() {
3414 if (PropertiesHelper::IsUserBuild()) {
3415 return;
3416 }
3417
3418 RunCommand(
3419 // Empty name because it's not intended to be classified as a bugreport section.
3420 // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
3421 "", {
3422 "/system/xbin/su", "system",
3423 "/system/bin/layertracegenerator",
3424 "/data/misc/wmtrace/transactions_trace.winscope",
3425 "/data/misc/wmtrace/layers_trace_from_transactions.winscope"
3426 },
3427 CommandOptions::WithTimeout(120).Always().RedirectStderr().Build());
3428}
3429
3430void Dumpstate::MaybeAddUiTracesToZip() {
3431 if (PropertiesHelper::IsUserBuild()) {
3432 return;
3433 }
3434
3435 ds.AddDir(WMTRACE_DATA_DIR, false);
Yohei Yukawa95305b32021-03-09 07:54:27 -08003436}
3437
Paul Changeb4b4642020-05-28 22:05:47 +08003438void Dumpstate::onUiIntensiveBugreportDumpsFinished(int32_t calling_uid) {
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003439 if (multiuser_get_app_id(calling_uid) == AID_SHELL || !CalledByApi()) {
Paul Changc490e662020-04-11 18:14:09 +08003440 return;
3441 }
3442 if (listener_ != nullptr) {
3443 // Let listener know ui intensive bugreport dumps are finished, then it can do event
3444 // handling if required.
Paul Changeb4b4642020-05-28 22:05:47 +08003445 listener_->onUiIntensiveBugreportDumpsFinished();
Paul Changc490e662020-04-11 18:14:09 +08003446 }
3447}
3448
Jichao Lie89d9c12019-11-21 19:02:51 -08003449void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) {
Gavin Corkerya44686c2022-11-23 18:16:51 +00003450 if (multiuser_get_app_id(calling_uid) == AID_SHELL ||
3451 !CalledByApi() || options_->is_consent_deferred) {
3452 // No need to get consent for shell triggered dumpstates, or not
3453 // through bugreporting API (i.e. no fd to copy back), or when consent
3454 // is deferred.
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003455 return;
3456 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003457 consent_callback_ = new ConsentCallback();
3458 const String16 incidentcompanion("incidentcompanion");
3459 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
Jichao Lie89d9c12019-11-21 19:02:51 -08003460 android::String16 package(calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003461 if (ics != nullptr) {
3462 MYLOGD("Checking user consent via incidentcompanion service\n");
Steven Leeb573eb82022-11-29 22:31:35 +08003463 int flags = 0x1; // IncidentManager.FLAG_CONFIRMATION_DIALOG
3464 if (IsConsentlessBugreportAllowed(*options_)) {
3465 flags |= 0x2; // IncidentManager.FLAG_ALLOW_CONSENTLESS_BUGREPORT
3466 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003467 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
Steven Leeb573eb82022-11-29 22:31:35 +08003468 calling_uid, package, String16(), String16(), flags, consent_callback_.get());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003469 } else {
3470 MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
3471 }
3472}
3473
Nandana Dutt5c390032019-03-12 10:52:56 +00003474bool Dumpstate::IsUserConsentDenied() const {
3475 return ds.consent_callback_ != nullptr &&
3476 ds.consent_callback_->getResult() == UserConsentResult::DENIED;
3477}
3478
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01003479bool Dumpstate::CalledByApi() const {
3480 return ds.options_->bugreport_fd.get() != -1 ? true : false;
3481}
3482
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003483void Dumpstate::CleanupTmpFiles() {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003484 android::os::UnlinkAndLogOnError(tmp_path_);
3485 android::os::UnlinkAndLogOnError(screenshot_path_);
3486 android::os::UnlinkAndLogOnError(path_);
Gavin Corkery789d7a52021-02-24 23:52:35 +00003487 if (dump_traces_path != nullptr) {
3488 android::os::UnlinkAndLogOnError(dump_traces_path);
3489 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003490}
3491
Rhed Jao5377d792020-07-16 17:37:39 +08003492void Dumpstate::EnableParallelRunIfNeeded() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003493 if (!PropertiesHelper::IsParallelRun()) {
Rhed Jao5377d792020-07-16 17:37:39 +08003494 return;
3495 }
3496 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003497 zip_entry_tasks_ = std::make_unique<TaskQueue>();
Rhed Jao5377d792020-07-16 17:37:39 +08003498}
3499
3500void Dumpstate::ShutdownDumpPool() {
3501 if (dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08003502 dump_pool_.reset();
Rhed Jao5377d792020-07-16 17:37:39 +08003503 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003504 if (zip_entry_tasks_) {
3505 zip_entry_tasks_->run(/* do_cancel = */true);
3506 zip_entry_tasks_ = nullptr;
3507 }
3508}
3509
3510void Dumpstate::EnqueueAddZipEntryAndCleanupIfNeeded(const std::string& entry_name,
3511 const std::string& entry_path) {
3512 auto func_add_zip_entry_and_cleanup = [=](bool task_cancelled) {
3513 if (!task_cancelled) {
3514 AddZipEntry(entry_name, entry_path);
3515 }
3516 android::os::UnlinkAndLogOnError(entry_path);
3517 };
3518 if (zip_entry_tasks_) {
3519 // Enqueues AddZipEntryAndCleanup function if the parallel run is enabled.
3520 zip_entry_tasks_->add(func_add_zip_entry_and_cleanup, _1);
3521 } else {
3522 // Invokes AddZipEntryAndCleanup immediately
3523 std::invoke(func_add_zip_entry_and_cleanup, /* task_cancelled = */false);
3524 }
Rhed Jao5377d792020-07-16 17:37:39 +08003525}
3526
Nandana Duttd2f5f082019-01-18 17:13:52 +00003527Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
3528 MYLOGD("User denied consent; deleting files and returning\n");
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003529 CleanupTmpFiles();
Nandana Duttd2f5f082019-01-18 17:13:52 +00003530 return USER_CONSENT_DENIED;
3531}
3532
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003533Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented(int32_t calling_uid) {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003534 // If the caller has asked to copy the bugreport over to their directory, we need explicit
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003535 // user consent (unless the caller is Shell).
3536 UserConsentResult consent_result;
Nikhil Kumar28ce35e2023-01-10 14:32:44 +00003537 if (multiuser_get_app_id(calling_uid) == AID_SHELL) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003538 consent_result = UserConsentResult::APPROVED;
3539 } else {
3540 consent_result = consent_callback_->getResult();
3541 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003542 if (consent_result == UserConsentResult::UNAVAILABLE) {
3543 // User has not responded yet.
3544 uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
Hunter Knepshield70610fa2020-01-03 15:27:33 -08003545 // Telephony is a fast report type, particularly on user builds where information may be
3546 // more aggressively limited. To give the user time to read the consent dialog, increase the
3547 // timeout.
3548 uint64_t timeout_ms = options_->telephony_only ? TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS
3549 : USER_CONSENT_TIMEOUT_MS;
3550 if (elapsed_ms < timeout_ms) {
3551 uint delay_seconds = (timeout_ms - elapsed_ms) / 1000;
Nandana Duttd2f5f082019-01-18 17:13:52 +00003552 MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
3553 sleep(delay_seconds);
3554 }
3555 consent_result = consent_callback_->getResult();
3556 }
3557 if (consent_result == UserConsentResult::DENIED) {
3558 // User has explicitly denied sharing with the app. To be safe delete the
3559 // internal bugreport & tmp files.
3560 return HandleUserConsentDenied();
3561 }
3562 if (consent_result == UserConsentResult::APPROVED) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00003563 bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
3564 if (copy_succeeded) {
3565 android::os::UnlinkAndLogOnError(path_);
Abhijeet Kaur9ce94672020-04-01 17:22:36 +01003566 if (options_->do_screenshot &&
3567 options_->screenshot_fd.get() != -1 &&
3568 !options_->is_screenshot_copied) {
3569 copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
3570 options_->screenshot_fd.get());
3571 options_->is_screenshot_copied = copy_succeeded;
3572 if (copy_succeeded) {
3573 android::os::UnlinkAndLogOnError(screenshot_path_);
3574 }
3575 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003576 }
3577 return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
3578 } else if (consent_result == UserConsentResult::UNAVAILABLE) {
3579 // consent_result is still UNAVAILABLE. The user has likely not responded yet.
3580 // Since we do not have user consent to share the bugreport it does not get
3581 // copied over to the calling app but remains in the internal directory from
3582 // where the user can manually pull it.
Paul Changce644212021-05-11 16:06:45 +08003583 std::string final_path = GetPath(".zip");
3584 bool copy_succeeded = android::os::CopyFileToFile(path_, final_path);
3585 if (copy_succeeded) {
3586 android::os::UnlinkAndLogOnError(path_);
3587 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003588 return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
3589 }
3590 // Unknown result; must be a programming error.
3591 MYLOGE("Unknown user consent result:%d\n", consent_result);
3592 return Dumpstate::RunStatus::ERROR;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003593}
3594
Nandana Duttf02564e2019-02-15 15:24:24 +00003595Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003596 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
3597 Dumpstate::RunStatus status = options->Initialize(argc, argv);
3598 if (status == Dumpstate::RunStatus::OK) {
Nandana Duttf02564e2019-02-15 15:24:24 +00003599 SetOptions(std::move(options));
Nandana Duttd2f5f082019-01-18 17:13:52 +00003600 // When directly running dumpstate binary, the output is not expected to be written
3601 // to any external file descriptor.
Nandana Duttf02564e2019-02-15 15:24:24 +00003602 assert(options_->bugreport_fd.get() == -1);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003603
3604 // calling_uid and calling_package are for user consent to share the bugreport with
Abhijeet Kaura407fb82020-03-27 12:51:12 +00003605 // an app; they are irrelevant here because bugreport is triggered via command line.
3606 // Update Last ID before calling Run().
3607 Initialize();
Nikhil Kumarb70622a2023-06-15 15:37:19 +01003608 status = Run(0 /* calling_uid */, "" /* calling_package */);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003609 }
Nandana Duttf02564e2019-02-15 15:24:24 +00003610 return status;
3611}
3612
3613/* Main entry point for dumpstate binary. */
3614int run_main(int argc, char* argv[]) {
3615 Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003616
3617 switch (status) {
3618 case Dumpstate::RunStatus::OK:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003619 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003620 case Dumpstate::RunStatus::HELP:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003621 ShowUsage();
3622 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003623 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003624 fprintf(stderr, "Invalid combination of args\n");
3625 ShowUsage();
3626 exit(1);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003627 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003628 FALLTHROUGH_INTENDED;
3629 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3630 FALLTHROUGH_INTENDED;
3631 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003632 exit(2);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003633 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003634}
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003635
3636// TODO(111441001): Default DumpOptions to sensible values.
3637Dumpstate::Dumpstate(const std::string& version)
3638 : pid_(getpid()),
3639 options_(new Dumpstate::DumpOptions()),
Nandana Dutt402a8392019-06-14 14:25:13 +01003640 last_reported_percent_progress_(0),
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003641 version_(version),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003642 now_(time(nullptr)),
3643 open_socket_fn_(open_socket) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003644}
3645
3646Dumpstate& Dumpstate::GetInstance() {
3647 static Dumpstate singleton_(android::base::GetProperty("dumpstate.version", VERSION_CURRENT));
3648 return singleton_;
3649}
3650
Rhed Jao5377d792020-07-16 17:37:39 +08003651DurationReporter::DurationReporter(const std::string& title, bool logcat_only, bool verbose,
3652 int duration_fd) : title_(title), logcat_only_(logcat_only), verbose_(verbose),
3653 duration_fd_(duration_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003654 if (!title_.empty()) {
3655 started_ = Nanotime();
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003656 if (title_.find("SHOW MAP") == std::string::npos) {
3657 ATRACE_ASYNC_BEGIN(title_.c_str(), 0);
3658 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003659 }
3660}
3661
3662DurationReporter::~DurationReporter() {
3663 if (!title_.empty()) {
3664 float elapsed = (float)(Nanotime() - started_) / NANOS_PER_SEC;
chenqiwuaf8b2d92019-12-12 18:53:51 +08003665 if (elapsed >= .5f || verbose_) {
3666 MYLOGD("Duration of '%s': %.2fs\n", title_.c_str(), elapsed);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003667 }
chenqiwuaf8b2d92019-12-12 18:53:51 +08003668 if (!logcat_only_) {
3669 // Use "Yoda grammar" to make it easier to grep|sort sections.
Rhed Jao5377d792020-07-16 17:37:39 +08003670 dprintf(duration_fd_, "------ %.3fs was the duration of '%s' ------\n",
3671 elapsed, title_.c_str());
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003672 }
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003673 if (title_.find("SHOW MAP") == std::string::npos) {
3674 ATRACE_ASYNC_END(title_.c_str(), 0);
3675 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003676 }
3677}
3678
3679const int32_t Progress::kDefaultMax = 5000;
3680
3681Progress::Progress(const std::string& path) : Progress(Progress::kDefaultMax, 1.1, path) {
3682}
3683
3684Progress::Progress(int32_t initial_max, int32_t progress, float growth_factor)
3685 : Progress(initial_max, growth_factor, "") {
3686 progress_ = progress;
3687}
3688
3689Progress::Progress(int32_t initial_max, float growth_factor, const std::string& path)
3690 : initial_max_(initial_max),
3691 progress_(0),
3692 max_(initial_max),
3693 growth_factor_(growth_factor),
3694 n_runs_(0),
3695 average_max_(0),
3696 path_(path) {
3697 if (!path_.empty()) {
3698 Load();
3699 }
3700}
3701
3702void Progress::Load() {
3703 MYLOGD("Loading stats from %s\n", path_.c_str());
3704 std::string content;
3705 if (!android::base::ReadFileToString(path_, &content)) {
3706 MYLOGI("Could not read stats from %s; using max of %d\n", path_.c_str(), max_);
3707 return;
3708 }
3709 if (content.empty()) {
3710 MYLOGE("No stats (empty file) on %s; using max of %d\n", path_.c_str(), max_);
3711 return;
3712 }
3713 std::vector<std::string> lines = android::base::Split(content, "\n");
3714
3715 if (lines.size() < 1) {
3716 MYLOGE("Invalid stats on file %s: not enough lines (%d). Using max of %d\n", path_.c_str(),
3717 (int)lines.size(), max_);
3718 return;
3719 }
3720 char* ptr;
3721 n_runs_ = strtol(lines[0].c_str(), &ptr, 10);
3722 average_max_ = strtol(ptr, nullptr, 10);
3723 if (n_runs_ <= 0 || average_max_ <= 0 || n_runs_ > STATS_MAX_N_RUNS ||
3724 average_max_ > STATS_MAX_AVERAGE) {
3725 MYLOGE("Invalid stats line on file %s: %s\n", path_.c_str(), lines[0].c_str());
3726 initial_max_ = Progress::kDefaultMax;
3727 } else {
3728 initial_max_ = average_max_;
3729 }
3730 max_ = initial_max_;
3731
3732 MYLOGI("Average max progress: %d in %d runs; estimated max: %d\n", average_max_, n_runs_, max_);
3733}
3734
3735void Progress::Save() {
3736 int32_t total = n_runs_ * average_max_ + progress_;
3737 int32_t runs = n_runs_ + 1;
3738 int32_t average = floor(((float)total) / runs);
3739 MYLOGI("Saving stats (total=%d, runs=%d, average=%d) on %s\n", total, runs, average,
3740 path_.c_str());
3741 if (path_.empty()) {
3742 return;
3743 }
3744
3745 std::string content = android::base::StringPrintf("%d %d\n", runs, average);
3746 if (!android::base::WriteStringToFile(content, path_)) {
3747 MYLOGE("Could not save stats on %s\n", path_.c_str());
3748 }
3749}
3750
3751int32_t Progress::Get() const {
3752 return progress_;
3753}
3754
3755bool Progress::Inc(int32_t delta_sec) {
3756 bool changed = false;
3757 if (delta_sec >= 0) {
3758 progress_ += delta_sec;
3759 if (progress_ > max_) {
3760 int32_t old_max = max_;
3761 max_ = floor((float)progress_ * growth_factor_);
3762 MYLOGD("Adjusting max progress from %d to %d\n", old_max, max_);
3763 changed = true;
3764 }
3765 }
3766 return changed;
3767}
3768
3769int32_t Progress::GetMax() const {
3770 return max_;
3771}
3772
3773int32_t Progress::GetInitialMax() const {
3774 return initial_max_;
3775}
3776
3777void Progress::Dump(int fd, const std::string& prefix) const {
3778 const char* pr = prefix.c_str();
3779 dprintf(fd, "%sprogress: %d\n", pr, progress_);
3780 dprintf(fd, "%smax: %d\n", pr, max_);
3781 dprintf(fd, "%sinitial_max: %d\n", pr, initial_max_);
3782 dprintf(fd, "%sgrowth_factor: %0.2f\n", pr, growth_factor_);
3783 dprintf(fd, "%spath: %s\n", pr, path_.c_str());
3784 dprintf(fd, "%sn_runs: %d\n", pr, n_runs_);
3785 dprintf(fd, "%saverage_max: %d\n", pr, average_max_);
3786}
3787
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003788std::string Dumpstate::GetPath(const std::string& suffix) const {
3789 return GetPath(bugreport_internal_dir_, suffix);
3790}
3791
3792std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
3793 return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
3794 name_.c_str(), suffix.c_str());
3795}
3796
3797void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
3798 progress_ = std::move(progress);
3799}
3800
3801void for_each_userid(void (*func)(int), const char *header) {
3802 std::string title = header == nullptr ? "for_each_userid" : android::base::StringPrintf(
3803 "for_each_userid(%s)", header);
3804 DurationReporter duration_reporter(title);
3805 if (PropertiesHelper::IsDryRun()) return;
3806
3807 DIR *d;
3808 struct dirent *de;
3809
3810 if (header) printf("\n------ %s ------\n", header);
3811 func(0);
3812
3813 if (!(d = opendir("/data/system/users"))) {
3814 printf("Failed to open /data/system/users (%s)\n", strerror(errno));
3815 return;
3816 }
3817
3818 while ((de = readdir(d))) {
3819 int userid;
3820 if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
3821 continue;
3822 }
3823 func(userid);
3824 }
3825
3826 closedir(d);
3827}
3828
3829static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
3830 DIR *d;
3831 struct dirent *de;
3832
3833 if (!(d = opendir("/proc"))) {
3834 printf("Failed to open /proc (%s)\n", strerror(errno));
3835 return;
3836 }
3837
3838 if (header) printf("\n------ %s ------\n", header);
3839 while ((de = readdir(d))) {
3840 if (ds.IsUserConsentDenied()) {
3841 MYLOGE(
3842 "Returning early because user denied consent to share bugreport with calling app.");
3843 closedir(d);
3844 return;
3845 }
3846 int pid;
3847 int fd;
3848 char cmdpath[255];
3849 char cmdline[255];
3850
3851 if (!(pid = atoi(de->d_name))) {
3852 continue;
3853 }
3854
3855 memset(cmdline, 0, sizeof(cmdline));
3856
3857 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
3858 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3859 TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
3860 close(fd);
3861 if (cmdline[0]) {
3862 helper(pid, cmdline, arg);
3863 continue;
3864 }
3865 }
3866
3867 // if no cmdline, a kernel thread has comm
3868 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
3869 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3870 TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
3871 close(fd);
3872 if (cmdline[1]) {
3873 cmdline[0] = '[';
3874 size_t len = strcspn(cmdline, "\f\b\r\n");
3875 cmdline[len] = ']';
3876 cmdline[len+1] = '\0';
3877 }
3878 }
3879 if (!cmdline[0]) {
3880 strcpy(cmdline, "N/A");
3881 }
3882 helper(pid, cmdline, arg);
3883 }
3884
3885 closedir(d);
3886}
3887
3888static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
3889 for_each_pid_func *func = (for_each_pid_func*) arg;
3890 func(pid, cmdline);
3891}
3892
3893void for_each_pid(for_each_pid_func func, const char *header) {
3894 std::string title = header == nullptr ? "for_each_pid"
3895 : android::base::StringPrintf("for_each_pid(%s)", header);
3896 DurationReporter duration_reporter(title);
3897 if (PropertiesHelper::IsDryRun()) return;
3898
3899 __for_each_pid(for_each_pid_helper, header, (void *) func);
3900}
3901
3902static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
3903 DIR *d;
3904 struct dirent *de;
3905 char taskpath[255];
3906 for_each_tid_func *func = (for_each_tid_func *) arg;
3907
3908 snprintf(taskpath, sizeof(taskpath), "/proc/%d/task", pid);
3909
3910 if (!(d = opendir(taskpath))) {
3911 printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
3912 return;
3913 }
3914
3915 func(pid, pid, cmdline);
3916
3917 while ((de = readdir(d))) {
3918 if (ds.IsUserConsentDenied()) {
3919 MYLOGE(
3920 "Returning early because user denied consent to share bugreport with calling app.");
3921 closedir(d);
3922 return;
3923 }
3924 int tid;
3925 int fd;
3926 char commpath[255];
3927 char comm[255];
3928
3929 if (!(tid = atoi(de->d_name))) {
3930 continue;
3931 }
3932
3933 if (tid == pid)
3934 continue;
3935
3936 snprintf(commpath, sizeof(commpath), "/proc/%d/comm", tid);
3937 memset(comm, 0, sizeof(comm));
3938 if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
3939 strcpy(comm, "N/A");
3940 } else {
3941 char *c;
3942 TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
3943 close(fd);
3944
3945 c = strrchr(comm, '\n');
3946 if (c) {
3947 *c = '\0';
3948 }
3949 }
3950 func(pid, tid, comm);
3951 }
3952
3953 closedir(d);
3954}
3955
3956void for_each_tid(for_each_tid_func func, const char *header) {
3957 std::string title = header == nullptr ? "for_each_tid"
3958 : android::base::StringPrintf("for_each_tid(%s)", header);
3959 DurationReporter duration_reporter(title);
3960
3961 if (PropertiesHelper::IsDryRun()) return;
3962
3963 __for_each_pid(for_each_tid_helper, header, (void *) func);
3964}
3965
3966void show_wchan(int pid, int tid, const char *name) {
3967 if (PropertiesHelper::IsDryRun()) return;
3968
3969 char path[255];
3970 char buffer[255];
3971 int fd, ret, save_errno;
3972 char name_buffer[255];
3973
3974 memset(buffer, 0, sizeof(buffer));
3975
3976 snprintf(path, sizeof(path), "/proc/%d/wchan", tid);
3977 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
3978 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
3979 return;
3980 }
3981
3982 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3983 save_errno = errno;
3984 close(fd);
3985
3986 if (ret < 0) {
3987 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
3988 return;
3989 }
3990
3991 snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
3992 pid == tid ? 0 : 3, "", name);
3993
3994 printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
3995
3996 return;
3997}
3998
3999// print time in centiseconds
4000static void snprcent(char *buffer, size_t len, size_t spc,
4001 unsigned long long time) {
4002 static long hz; // cache discovered hz
4003
4004 if (hz <= 0) {
4005 hz = sysconf(_SC_CLK_TCK);
4006 if (hz <= 0) {
4007 hz = 1000;
4008 }
4009 }
4010
4011 // convert to centiseconds
4012 time = (time * 100 + (hz / 2)) / hz;
4013
4014 char str[16];
4015
4016 snprintf(str, sizeof(str), " %llu.%02u",
4017 time / 100, (unsigned)(time % 100));
4018 size_t offset = strlen(buffer);
4019 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
4020 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
4021}
4022
4023// print permille as a percent
4024static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
4025 char str[16];
4026
4027 snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
4028 size_t offset = strlen(buffer);
4029 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
4030 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
4031}
4032
4033void show_showtime(int pid, const char *name) {
4034 if (PropertiesHelper::IsDryRun()) return;
4035
4036 char path[255];
4037 char buffer[1023];
4038 int fd, ret, save_errno;
4039
4040 memset(buffer, 0, sizeof(buffer));
4041
4042 snprintf(path, sizeof(path), "/proc/%d/stat", pid);
4043 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
4044 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
4045 return;
4046 }
4047
4048 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
4049 save_errno = errno;
4050 close(fd);
4051
4052 if (ret < 0) {
4053 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
4054 return;
4055 }
4056
4057 // field 14 is utime
4058 // field 15 is stime
4059 // field 42 is iotime
4060 unsigned long long utime = 0, stime = 0, iotime = 0;
4061 if (sscanf(buffer,
4062 "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
4063 "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
4064 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
4065 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
4066 &utime, &stime, &iotime) != 3) {
4067 return;
4068 }
4069
4070 unsigned long long total = utime + stime;
4071 if (!total) {
4072 return;
4073 }
4074
4075 unsigned permille = (iotime * 1000 + (total / 2)) / total;
4076 if (permille > 1000) {
4077 permille = 1000;
4078 }
4079
4080 // try to beautify and stabilize columns at <80 characters
4081 snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
4082 if ((name[0] != '[') || utime) {
4083 snprcent(buffer, sizeof(buffer), 57, utime);
4084 }
4085 snprcent(buffer, sizeof(buffer), 65, stime);
4086 if ((name[0] != '[') || iotime) {
4087 snprcent(buffer, sizeof(buffer), 73, iotime);
4088 }
4089 if (iotime) {
4090 snprdec(buffer, sizeof(buffer), 79, permille);
4091 }
4092 puts(buffer); // adds a trailing newline
4093
4094 return;
4095}
4096
4097void do_dmesg() {
4098 const char *title = "KERNEL LOG (dmesg)";
4099 DurationReporter duration_reporter(title);
4100 printf("------ %s ------\n", title);
4101
4102 if (PropertiesHelper::IsDryRun()) return;
4103
4104 /* Get size of kernel buffer */
4105 int size = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
4106 if (size <= 0) {
4107 printf("Unexpected klogctl return value: %d\n\n", size);
4108 return;
4109 }
4110 char *buf = (char *) malloc(size + 1);
4111 if (buf == nullptr) {
4112 printf("memory allocation failed\n\n");
4113 return;
4114 }
4115 int retval = klogctl(KLOG_READ_ALL, buf, size);
4116 if (retval < 0) {
4117 printf("klogctl failure\n\n");
4118 free(buf);
4119 return;
4120 }
4121 buf[retval] = '\0';
4122 printf("%s\n\n", buf);
4123 free(buf);
4124 return;
4125}
4126
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004127int Dumpstate::DumpFile(const std::string& title, const std::string& path) {
4128 DurationReporter duration_reporter(title);
4129
4130 int status = DumpFileToFd(STDOUT_FILENO, title, path);
4131
4132 UpdateProgress(WEIGHT_FILE);
4133
4134 return status;
4135}
4136
4137int read_file_as_long(const char *path, long int *output) {
4138 int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
4139 if (fd < 0) {
4140 int err = errno;
4141 MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
4142 return -1;
4143 }
4144 char buffer[50];
4145 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
4146 if (bytes_read == -1) {
4147 MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
4148 return -2;
4149 }
4150 if (bytes_read == 0) {
4151 MYLOGE("File %s is empty\n", path);
4152 return -3;
4153 }
4154 *output = atoi(buffer);
4155 return 0;
4156}
4157
4158/* calls skip to gate calling dump_from_fd recursively
4159 * in the specified directory. dump_from_fd defaults to
4160 * dump_file_from_fd above when set to NULL. skip defaults
4161 * to false when set to NULL. dump_from_fd will always be
4162 * called with title NULL.
4163 */
4164int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
4165 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4166 DurationReporter duration_reporter(title);
4167 DIR *dirp;
4168 struct dirent *d;
4169 char *newpath = nullptr;
4170 const char *slash = "/";
4171 int retval = 0;
4172
4173 if (!title.empty()) {
4174 printf("------ %s (%s) ------\n", title.c_str(), dir);
4175 }
4176 if (PropertiesHelper::IsDryRun()) return 0;
4177
4178 if (dir[strlen(dir) - 1] == '/') {
4179 ++slash;
4180 }
4181 dirp = opendir(dir);
4182 if (dirp == nullptr) {
4183 retval = -errno;
4184 MYLOGE("%s: %s\n", dir, strerror(errno));
4185 return retval;
4186 }
4187
4188 if (!dump_from_fd) {
4189 dump_from_fd = dump_file_from_fd;
4190 }
4191 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4192 if ((d->d_name[0] == '.')
4193 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4194 || (d->d_name[1] == '\0'))) {
4195 continue;
4196 }
4197 asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
4198 (d->d_type == DT_DIR) ? "/" : "");
4199 if (!newpath) {
4200 retval = -errno;
4201 continue;
4202 }
4203 if (skip && (*skip)(newpath)) {
4204 continue;
4205 }
4206 if (d->d_type == DT_DIR) {
4207 int ret = dump_files("", newpath, skip, dump_from_fd);
4208 if (ret < 0) {
4209 retval = ret;
4210 }
4211 continue;
4212 }
4213 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
4214 if (fd.get() < 0) {
4215 retval = -1;
4216 printf("*** %s: %s\n", newpath, strerror(errno));
4217 continue;
4218 }
4219 (*dump_from_fd)(nullptr, newpath, fd.get());
4220 }
4221 closedir(dirp);
4222 if (!title.empty()) {
4223 printf("\n");
4224 }
4225 return retval;
4226}
4227
4228/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
4229 * it's possible to avoid issues where opening the file itself can get
4230 * stuck.
4231 */
4232int dump_file_from_fd(const char *title, const char *path, int fd) {
4233 if (PropertiesHelper::IsDryRun()) return 0;
4234
4235 int flags = fcntl(fd, F_GETFL);
4236 if (flags == -1) {
4237 printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
4238 return -1;
4239 } else if (!(flags & O_NONBLOCK)) {
4240 printf("*** %s: fd must have O_NONBLOCK set.\n", path);
4241 return -1;
4242 }
4243 return DumpFileFromFdToFd(title, path, fd, STDOUT_FILENO, PropertiesHelper::IsDryRun());
4244}
4245
4246int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004247 const CommandOptions& options, bool verbose_duration, int out_fd) {
4248 DurationReporter duration_reporter(title, false /* logcat_only */,
4249 verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004250
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004251 int status = RunCommandToFd(out_fd, title, full_command, options);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004252
4253 /* TODO: for now we're simplifying the progress calculation by using the
4254 * timeout as the weight. It's a good approximation for most cases, except when calling dumpsys,
4255 * where its weight should be much higher proportionally to its timeout.
4256 * Ideally, it should use a options.EstimatedDuration() instead...*/
4257 UpdateProgress(options.Timeout());
4258
4259 return status;
4260}
4261
4262void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
Rhed Jaoe017f982020-07-21 17:58:41 +08004263 const CommandOptions& options, long dumpsysTimeoutMs, int out_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004264 long timeout_ms = dumpsysTimeoutMs > 0 ? dumpsysTimeoutMs : options.TimeoutInMs();
4265 std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-T", std::to_string(timeout_ms)};
4266 dumpsys.insert(dumpsys.end(), dumpsys_args.begin(), dumpsys_args.end());
Rhed Jaoe017f982020-07-21 17:58:41 +08004267 RunCommand(title, dumpsys, options, false, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004268}
4269
Dieter Hsu105ad0c2020-09-29 15:23:33 +08004270static int open_socket(const char* service) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004271 int s = android_get_control_socket(service);
4272 if (s < 0) {
4273 MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
4274 return -1;
4275 }
4276 fcntl(s, F_SETFD, FD_CLOEXEC);
4277
4278 // Set backlog to 0 to make sure that queue size will be minimum.
4279 // In Linux, because the minimum queue will be 1, connect() will be blocked
4280 // if the other clients already called connect() and the connection request was not accepted.
4281 if (listen(s, 0) < 0) {
4282 MYLOGE("listen(control socket): %s\n", strerror(errno));
4283 return -1;
4284 }
4285
4286 struct sockaddr addr;
4287 socklen_t alen = sizeof(addr);
Abhijeet Kaur2113cae2019-09-13 09:24:15 +01004288 int fd = accept4(s, &addr, &alen, SOCK_CLOEXEC);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004289
4290 // Close socket just after accept(), to make sure that connect() by client will get error
4291 // when the socket is used by the other services.
4292 // There is still a race condition possibility between accept and close, but there is no way
4293 // to close-on-accept atomically.
4294 // See detail; b/123306389#comment25
4295 close(s);
4296
4297 if (fd < 0) {
4298 MYLOGE("accept(control socket): %s\n", strerror(errno));
4299 return -1;
4300 }
4301
4302 return fd;
4303}
4304
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004305// TODO: should call is_valid_output_file and/or be merged into it.
4306void create_parent_dirs(const char *path) {
4307 char *chp = const_cast<char *> (path);
4308
4309 /* skip initial slash */
4310 if (chp[0] == '/')
4311 chp++;
4312
4313 /* create leading directories, if necessary */
4314 struct stat dir_stat;
4315 while (chp && chp[0]) {
4316 chp = strchr(chp, '/');
4317 if (chp) {
4318 *chp = 0;
4319 if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
4320 MYLOGI("Creating directory %s\n", path);
4321 if (mkdir(path, 0770)) { /* drwxrwx--- */
4322 MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
4323 } else if (chown(path, AID_SHELL, AID_SHELL)) {
4324 MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
4325 }
4326 }
4327 *chp++ = '/';
4328 }
4329 }
4330}
4331
4332bool _redirect_to_file(FILE* redirect, char* path, int truncate_flag) {
4333 create_parent_dirs(path);
4334
4335 int fd = TEMP_FAILURE_RETRY(open(path,
4336 O_WRONLY | O_CREAT | truncate_flag | O_CLOEXEC | O_NOFOLLOW,
4337 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
4338 if (fd < 0) {
4339 MYLOGE("%s: %s\n", path, strerror(errno));
4340 return false;
4341 }
4342
4343 TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
4344 close(fd);
4345 return true;
4346}
4347
4348bool redirect_to_file(FILE* redirect, char* path) {
4349 return _redirect_to_file(redirect, path, O_TRUNC);
4350}
4351
4352bool redirect_to_existing_file(FILE* redirect, char* path) {
4353 return _redirect_to_file(redirect, path, O_APPEND);
4354}
4355
4356void dump_route_tables() {
4357 DurationReporter duration_reporter("DUMP ROUTE TABLES");
4358 if (PropertiesHelper::IsDryRun()) return;
4359 const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
4360 ds.DumpFile("RT_TABLES", RT_TABLES_PATH);
4361 FILE* fp = fopen(RT_TABLES_PATH, "re");
4362 if (!fp) {
4363 printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
4364 return;
4365 }
4366 char table[16];
4367 // Each line has an integer (the table number), a space, and a string (the table name). We only
4368 // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
4369 // Add a fixed max limit so this doesn't go awry.
4370 for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
4371 RunCommand("ROUTE TABLE IPv4", {"ip", "-4", "route", "show", "table", table});
4372 RunCommand("ROUTE TABLE IPv6", {"ip", "-6", "route", "show", "table", table});
4373 }
4374 fclose(fp);
4375}
4376
Li Li830179f2022-01-04 12:53:29 -08004377void dump_frozen_cgroupfs(const char *dir, int level,
4378 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4379 DIR *dirp;
4380 struct dirent *d;
4381 char *newpath = nullptr;
4382
4383 dirp = opendir(dir);
4384 if (dirp == nullptr) {
4385 MYLOGE("%s: %s\n", dir, strerror(errno));
4386 return;
4387 }
4388
4389 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4390 if ((d->d_name[0] == '.')
4391 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4392 || (d->d_name[1] == '\0'))) {
4393 continue;
4394 }
4395 if (d->d_type == DT_DIR) {
4396 asprintf(&newpath, "%s/%s/", dir, d->d_name);
4397 if (!newpath) {
4398 continue;
4399 }
4400 if (level == 0 && !strncmp(d->d_name, "uid_", 4)) {
4401 dump_frozen_cgroupfs(newpath, 1, dump_from_fd);
4402 } else if (level == 1 && !strncmp(d->d_name, "pid_", 4)) {
4403 char *freezer = nullptr;
4404 asprintf(&freezer, "%s/%s", newpath, "cgroup.freeze");
4405 if (freezer) {
4406 FILE* fp = fopen(freezer, "r");
4407 if (fp != NULL) {
4408 int frozen;
4409 fscanf(fp, "%d", &frozen);
4410 if (frozen > 0) {
4411 dump_files("", newpath, skip_none, dump_from_fd);
4412 }
4413 fclose(fp);
4414 }
4415 free(freezer);
4416 }
4417 }
4418 }
4419 }
4420 closedir(dirp);
4421}
4422
4423void dump_frozen_cgroupfs() {
Li Li830179f2022-01-04 12:53:29 -08004424 MYLOGD("Adding frozen processes from %s\n", CGROUPFS_DIR);
4425 DurationReporter duration_reporter("FROZEN CGROUPFS");
4426 if (PropertiesHelper::IsDryRun()) return;
4427 dump_frozen_cgroupfs(CGROUPFS_DIR, 0, _add_file_from_fd);
4428}
4429
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004430void Dumpstate::UpdateProgress(int32_t delta_sec) {
4431 if (progress_ == nullptr) {
4432 MYLOGE("UpdateProgress: progress_ not set\n");
4433 return;
4434 }
Rhed Jaobf63d8a2020-07-21 15:42:55 +08004435 // This function updates progress related members of the dumpstate and reports
4436 // progress percentage to the bugreport client. Since it could be called by
4437 // different dump tasks at the same time if the parallel run is enabled, a
4438 // mutex lock is necessary here to synchronize the call.
4439 std::lock_guard<std::recursive_mutex> lock(mutex_);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004440
4441 // Always update progess so stats can be tuned...
Nandana Dutt402a8392019-06-14 14:25:13 +01004442 progress_->Inc(delta_sec);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004443
4444 // ...but only notifiy listeners when necessary.
4445 if (!options_->do_progress_updates) return;
4446
4447 int progress = progress_->Get();
4448 int max = progress_->GetMax();
Nandana Dutt402a8392019-06-14 14:25:13 +01004449 int percent = 100 * progress / max;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004450
Nandana Dutt402a8392019-06-14 14:25:13 +01004451 if (last_reported_percent_progress_ > 0 && percent <= last_reported_percent_progress_) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004452 return;
4453 }
Nandana Dutt402a8392019-06-14 14:25:13 +01004454 last_reported_percent_progress_ = percent;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004455
4456 if (control_socket_fd_ >= 0) {
4457 dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
4458 fsync(control_socket_fd_);
4459 }
4460
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004461 if (listener_ != nullptr) {
Nandana Dutt235c6672019-11-14 15:22:32 +00004462 if (percent % 10 == 0) {
4463 // We don't want to spam logcat, so only log multiples of 10.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004464 MYLOGD("Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004465 } else {
4466 // stderr is ignored on normal invocations, but useful when calling
4467 // /system/bin/dumpstate directly for debuggging.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004468 fprintf(stderr, "Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004469 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004470
4471 listener_->onProgress(percent);
4472 }
4473}
4474
4475void Dumpstate::TakeScreenshot(const std::string& path) {
4476 const std::string& real_path = path.empty() ? screenshot_path_ : path;
4477 int status =
4478 RunCommand("", {"/system/bin/screencap", "-p", real_path},
4479 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
4480 if (status == 0) {
4481 MYLOGD("Screenshot saved on %s\n", real_path.c_str());
4482 } else {
4483 MYLOGE("Failed to take screenshot on %s\n", real_path.c_str());
4484 }
Paul Chang0d2aad72020-02-13 20:04:03 +08004485 if (listener_ != nullptr) {
4486 // Show a visual indication to indicate screenshot is taken via
4487 // IDumpstateListener.onScreenshotTaken()
4488 listener_->onScreenshotTaken(status == 0);
4489 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004490}
4491
4492bool is_dir(const char* pathname) {
4493 struct stat info;
4494 if (stat(pathname, &info) == -1) {
4495 return false;
4496 }
4497 return S_ISDIR(info.st_mode);
4498}
4499
4500time_t get_mtime(int fd, time_t default_mtime) {
4501 struct stat info;
4502 if (fstat(fd, &info) == -1) {
4503 return default_mtime;
4504 }
4505 return info.st_mtime;
4506}